"""Maître vectoriel de l'identité META.

Les lettres sont converties en courbes : le SVG ne dépend d'aucune police installée.
Le triangle du A est le contre-poinçon du glyphe, isolé et rempli séparément — ce n'est pas
un triangle dessiné par-dessus, c'est le trou de la lettre, donc il reste juste à toute taille.
"""
import math
from fontTools.ttLib import TTFont
from fontTools.varLib.instancer import instantiateVariableFont
from fontTools.pens.svgPathPen import SVGPathPen
from fontTools.pens.recordingPen import RecordingPen
import customA

FONT='/Users/saidzouhdi/Documents/COS/04-Implementation/cos/ops/META27-site/cfp/Sora.ttf'
GOLD='#d8b46a'; GOLD_D='#86682c'; NAVY='#06121c'; WHITE='#ffffff'; CREAM='#f7f6f1'
SIG='#96a8b4'
RINGS=[(0.33,0.62,0.265,145),(0.68,0.34,0.175,-15),(0.75,0.735,0.115,-15)]
RINGS_ICON=[(0.38,0.50,0.300,145),(0.775,0.755,0.155,-15)]
STROKE=0.095; GAP=18

_cache={}
def face(weight=800):
    if weight not in _cache:
        f=TTFont(FONT)
        try: f=instantiateVariableFont(f,{'wght':weight},inplace=False,updateFontNames=False)
        except Exception: pass
        _cache[weight]=f
    return _cache[weight]

def glyph_paths(text, size, weight=800, letterspacing=0.0, hole_char=None, use_custom_A=False):
    """Un chemin par lettre, tous contours réunis, destiné à fill-rule="evenodd" :
    les contre-poinçons (O, A, R…) restent donc des trous. Seul le contre-poinçon de
    hole_char est renvoyé à part, pour être rempli d'une autre couleur par-dessus."""
    f=face(weight); upm=f['head'].unitsPerEm; gs=f.getGlyphSet(); cmap=f.getBestCmap()
    k=size/upm
    letters=[]; holes=[]; x=0
    for ch in text:
        gn=cmap.get(ord(ch))
        if gn is None: continue
        if ch=='A' and use_custom_A:
            dstr, hole_d, adv = customA.paths()
            letters.append((dstr, x*k, k))
            if hole_char=='A': holes.append((hole_d, x*k, k))
            x+=adv + letterspacing*upm
            continue
        pen=SVGPathPen(gs); gs[gn].draw(pen); dstr=pen.getCommands()
        if dstr: letters.append((dstr, x*k, k))
        if hole_char and ch==hole_char:
            rec=RecordingPen(); gs[gn].draw(rec)
            contours=[]; cur=[]
            for op,args in rec.value:
                cur.append((op,args))
                if op=='closePath': contours.append(cur); cur=[]
            if cur: contours.append(cur)
            def bbox_area(c):
                pts=[p for op,a in c for p in a if isinstance(p,tuple)]
                if not pts: return 0
                xs=[p[0] for p in pts]; ys=[p[1] for p in pts]
                return (max(xs)-min(xs))*(max(ys)-min(ys))
            contours.sort(key=bbox_area, reverse=True)
            for c in contours[1:]:
                p2=SVGPathPen(gs)
                for op,args in c: getattr(p2,op)(*args)
                if p2.getCommands(): holes.append((p2.getCommands(), x*k, k))
        x+=gs[gn].width + letterspacing*upm
    return letters, holes, x*k, f['hhea'].ascent*k

def path_group(items, fill, y_base, evenodd=True):
    fr=' fill-rule="evenodd"' if evenodd else ''
    return '\n    '.join(
        f'<g transform="translate({dx:.2f},{y_base:.2f}) scale({k:.6f},{-k:.6f})">'
        f'<path d="{d}" fill="{fill}"{fr}/></g>' for d,dx,k in items)

def ring_paths(S, col, rings=RINGS, stroke=STROKE, gap=GAP, ox=0.0, oy=0.0):
    st=stroke*S; out=[]
    for cx,cy,r,g in rings:
        X,Y,R=cx*S+ox, cy*S+oy, r*S
        a0=math.radians(g+gap/2); a1=math.radians(g-gap/2+360)
        sx,sy=X+R*math.cos(a0), Y+R*math.sin(a0)
        ex,ey=X+R*math.cos(a1), Y+R*math.sin(a1)
        laf=1 if (math.degrees(a1-a0)%360)>180 else 0
        out.append(f'<path d="M {sx:.2f} {sy:.2f} A {R:.2f} {R:.2f} 0 {laf} 1 {ex:.2f} {ey:.2f}" '
                   f'fill="none" stroke="{col}" stroke-width="{st:.2f}" stroke-linecap="butt"/>')
    return '\n    '.join(out)

def svg_symbol(S=1000, col=GOLD, rings=RINGS, bg=None):
    b=f'<rect width="{S}" height="{S}" fill="{bg}"/>\n    ' if bg else ''
    return (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {S} {S}" width="{S}" height="{S}">\n'
            f'    {b}{ring_paths(S,col,rings)}\n</svg>\n')

def svg_lockup(H=400, ring_col=GOLD, text_col=WHITE, tri_col=GOLD, sig_col=SIG,
               tagline=True, bg=None):
    sym_f, word_f = (0.60,0.52) if tagline else (0.60,0.58)
    S=H*sym_f; pad=H*0.06; gap=H*0.17
    ws=H*word_f
    outer,holes,ww,asc=glyph_paths('META',ws,hole_char='A',use_custom_A=True)
    tag='METAMATERIALS  ·  PHOTONIC CRYSTALS  ·  PLASMONICS'
    ts=H*0.115
    to,th,tw,_=glyph_paths(tag,ts,weight=400,letterspacing=0.06)
    text_w=max(ww,tw if tagline else 0)
    W=pad+S+gap+text_w+pad
    x0=pad+gap+S
    body=[ring_paths(S,ring_col,RINGS,ox=pad,oy=(H-S)/2)]
    yb=H*0.24+ws*0.74 if tagline else (H+ws*0.72)/2
    body.append(f'<g transform="translate({x0:.2f},0)">{path_group(outer,text_col,yb)}</g>')
    body.append(f'<g transform="translate({x0:.2f},0)">{path_group(holes,tri_col,yb,evenodd=False)}</g>')
    if tagline:
        yt=H*0.645+ts*0.74
        body.append(f'<g transform="translate({x0:.2f},0)">{path_group(to,sig_col,yt)}</g>')
    b=f'<rect width="{W:.0f}" height="{H}" fill="{bg}"/>\n    ' if bg else ''
    return (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W:.0f} {H}" '
            f'width="{W:.0f}" height="{H}">\n    {b}'+'\n    '.join(body)+'\n</svg>\n')
