"""Useful digital, print and clothing applications made from the same master."""
import json
from pathlib import Path
from html import escape
from io import BytesIO
from pypdf import PdfReader,PdfWriter
from pypdf.generic import RectangleObject
from graphics import *
from identity import recolor,compact_logo

def fit(s,logo,x,y,w,h=None,kind='colour'):
    scale=w/logo.w
    if h is not None:scale=min(scale,h/logo.h)
    s.add(recolor(logo,kind),x,y,scale)
    return scale

def live_field(s,f,fields,key,text,x,y,height,face='body',colour=INK):
    font=f[face];role='field-'+key
    font.text(s,text,x,y,height,fill=colour,role=role)
    bounds=font.glyph('H')[1];size=height/(bounds[3]-bounds[1])*font.upem
    fields.append({'key':key,'text':text,'x':x,'y':y+height,'size':size,'face':face,'colour':colour})

def template(s,fields,path,physical=None):
    s.export(path,png_width=min(int(s.w),1600),physical=physical,transparent=False)
    base=Scene(s.w,s.h,title=s.title+' | Editable template')
    base.items=[i for i in s.items if not i['role'].startswith('field-')]
    svg=base.svg().replace('</svg>','')
    svg+='''\n<defs><style>
@font-face{font-family:STFDisplay;src:url('../fonts/anton/Anton-Regular.ttf')}
@font-face{font-family:STFText;src:url('../fonts/epilogue/Epilogue[wght].ttf');font-weight:100 900}
</style></defs>\n'''
    for field in fields:
        family='STFDisplay' if field['face']=='display' else 'STFText'
        weight={'body':400,'medium':600,'light':300,'display':400}[field['face']]
        svg+=f'<text data-editable="{field["key"]}" x="{field["x"]}" y="{field["y"]}" font-family="{family}" font-size="{field["size"]}" font-weight="{weight}" fill="{field["colour"]}">{escape(field["text"])}</text>\n'
    Path(path).with_suffix('.svg').write_text(svg+'</svg>\n')

def pdf_with_bleed(scene,path,trim_mm,bleed_mm=3):
    tw,th=trim_mm;px=scene.w/tw;bleed=bleed_mm*px
    s=Scene(scene.w+2*bleed,scene.h+2*bleed,title=scene.title+' | CMYK with 3 mm bleed')
    s.rect(0,0,s.w,s.h,PAPER);s.add(scene,bleed,bleed)
    physical=((tw+2*bleed_mm)/25.4*72,(th+2*bleed_mm)/25.4*72)
    reader=PdfReader(BytesIO(s.pdf(physical,cmyk=True)));writer=PdfWriter();p=reader.pages[0]
    b=bleed_mm/25.4*72
    p.trimbox=RectangleObject([b,b,physical[0]-b,physical[1]-b]);p.bleedbox=RectangleObject([0,0,*physical])
    writer.add_page(p);writer.add_metadata({'/Title':s.title,'/Author':'Stand The Fight'})
    with open(path,'wb') as out:writer.write(out)

def build_applications(f,mark,pmark,logos):
    for folder in ['social','web','print','patches','guide','previews']:(ROOT/folder).mkdir(exist_ok=True)
    # Square emblem with ample clearance for circular avatar crops.
    av=Scene(1024,1024,title='Stand The Fight | Social avatar')
    av.rect(0,0,1024,1024,PAPER);scale=1.42
    av.add(pmark,(1024-pmark.w*scale)/2,(1024-pmark.h*scale)/2,scale)
    av.export(ROOT/'social/stf-avatar-light',png_width=1024,transparent=False)
    avd=Scene(1024,1024,title='Stand The Fight | Dark social avatar');avd.rect(0,0,1024,1024,INK)
    avd.add(recolor(pmark,'reverse'),(1024-pmark.w*scale)/2,(1024-pmark.h*scale)/2,scale)
    avd.export(ROOT/'social/stf-avatar-dark',png_width=1024,transparent=False)
    icon=Scene(512,512,title='Stand The Fight | App icon');icon.rect(0,0,512,512,PAPER)
    icon.add(pmark,(512-pmark.w*.75)/2,(512-pmark.h*.75)/2,.75)
    (ROOT/'web/stf-icon.svg').write_text(icon.svg())
    for size in [32,48,64,180,192,512]:icon.png(size,False).save(ROOT/'web'/f'stf-icon-{size}.png')
    icon.png(64,False).save(ROOT/'web/favicon.ico',format='ICO',sizes=[(16,16),(32,32),(48,48),(64,64)])
    scenes={}
    # Editable templates deliberately contain field labels, never invented class facts.
    for name,w,h in [('square',1080,1080),('portrait',1080,1350),('story',1080,1920)]:
        s=Scene(w,h,title=f'Stand The Fight | {name.title()} social template');s.rect(0,0,w,h,PAPER);fields=[]
        f['medium'].text(s,'STAND THE FIGHT',64,60,20,tracking=.04)
        s.rect(64,110,70,8,RED)
        live_field(s,f,fields,'headline-1','CLASS',64,175,155,'display')
        live_field(s,f,fields,'headline-2','UPDATE',64,353,155,'display')
        live_field(s,f,fields,'date-time','DATE / TIME',68,570,27,'medium')
        live_field(s,f,fields,'venue','VENUE / CONTACT',68,622,22,'body')
        if h>1200:
            live_field(s,f,fields,'details','ADD YOUR CLASS DETAILS',68,698,19,'body')
        fit(s,logos['english'],44,h-386,420,340)
        s.line(520,h-120,w-64,h-120,INK,2)
        f['light'].text(s,'TRADITIONAL JAPANESE',w-64,h-90,14,tracking=.08,align='right')
        f['light'].text(s,'JIU-JITSU',w-64,h-62,14,tracking=.13,align='right')
        template(s,fields,ROOT/'social'/f'stf-{name}-template')
        scenes[name]=s
    banner=Scene(1600,600,title='Stand The Fight | Web and social banner');banner.rect(0,0,1600,600,INK)
    fit(banner,logos['primary'],32,10,640,570,'reverse')
    f['light'].text(banner,'TRADITIONAL JAPANESE',775,212,25,tracking=.11,fill=WHITE)
    f['display'].text(banner,'JIU-JITSU',768,270,96,width=700,fill=WHITE)
    banner.rect(775,407,78,7,RED)
    banner.export(ROOT/'web/stf-banner-1600x600',png_width=1600,transparent=False);scenes['banner']=banner
    # A clean, blank letterhead, with branding and footer only.
    letter=Scene(840,1188,title='Stand The Fight | A4 letterhead')
    letter.rect(0,0,840,1188,WHITE);fit(letter,logos['english'],43,28,225,200)
    letter.line(64,1080,776,1080,RULE,1)
    f['body'].text(letter,'STAND THE FIGHT',64,1114,12,tracking=.06)
    f['light'].text(letter,'TRADITIONAL JAPANESE JIU-JITSU',776,1114,10,align='right')
    letter.export(ROOT/'print/stf-letterhead-a4',png_width=1260,physical=(210/25.4*72,297/25.4*72),transparent=False)
    scenes['letterhead']=letter
    # A3 poster with live fields, plus CMYK print PDF and bleed/trim boxes.
    poster=Scene(1188,1680,title='Stand The Fight | A3 class poster template');poster.rect(0,0,1188,1680,PAPER);fields=[]
    fit(poster,logos['primary'],44,22,500,440)
    poster.line(72,490,1116,490,INK,2)
    live_field(poster,f,fields,'title-line-1','TRADITIONAL',72,554,128,'display')
    live_field(poster,f,fields,'title-line-2','JAPANESE',72,712,128,'display')
    live_field(poster,f,fields,'title-line-3','JIU-JITSU',72,870,128,'display')
    poster.rect(72,1084,95,9,RED)
    live_field(poster,f,fields,'date-time','DATE / TIME',72,1195,32,'medium')
    live_field(poster,f,fields,'venue','VENUE / ADDRESS',72,1262,27,'body')
    live_field(poster,f,fields,'contact','CONTACT / BOOKING DETAILS',72,1322,24,'body')
    f['light'].text(poster,'STAND THE FIGHT',72,1571,18,tracking=.12)
    template(poster,fields,ROOT/'print/stf-poster-a3-template',physical=(297/25.4*72,420/25.4*72))
    pdf_with_bleed(poster,ROOT/'print/stf-poster-a3-template-cmyk-3mm-bleed.pdf',(297,420));scenes['poster']=poster
    # 85 x 55 mm cards, front identity / back editable contact fields.
    front=Scene(850,550,title='Stand The Fight | 85 x 55 mm card front');front.rect(0,0,850,550,PAPER)
    fit(front,logos['primary'],115,-2,620,555)
    front.export(ROOT/'print/stf-card-front-85x55mm',png_width=1700,physical=(85/25.4*72,55/25.4*72),transparent=False)
    pdf_with_bleed(front,ROOT/'print/stf-card-front-cmyk-3mm-bleed.pdf',(85,55))
    back=Scene(850,550,title='Stand The Fight | Contact card template');back.rect(0,0,850,550,PAPER);fields=[]
    live_field(back,f,fields,'name','INSTRUCTOR NAME',55,70,32,'medium')
    live_field(back,f,fields,'role','ROLE / QUALIFICATION',55,130,18,'light')
    back.rect(55,199,50,5,RED)
    live_field(back,f,fields,'contact-1','PHONE / EMAIL',55,270,21,'body')
    live_field(back,f,fields,'contact-2','WEBSITE / SOCIAL',55,318,21,'body')
    live_field(back,f,fields,'venue','VENUE / ADDRESS',55,366,21,'body')
    template(back,fields,ROOT/'print/stf-card-back-template-85x55mm',physical=(85/25.4*72,55/25.4*72))
    pdf_with_bleed(back,ROOT/'print/stf-card-back-template-cmyk-3mm-bleed.pdf',(85,55))
    scenes['card-front']=front;scenes['card-back']=back
    # Vector process-colour handoff, 100 mm wide; black maps to K100.
    for name in ['primary','english','compact','emblem']:
        logo=logos[name];physical=(100/25.4*72,100/25.4*72*logo.h/logo.w)
        (ROOT/'print'/f'stf-{name}-100mm-cmyk.pdf').write_bytes(logo.pdf(physical,cmyk=True))
    # Two-colour shirt artwork: same full English logo, no new mascot/slogan.
    clothing=Scene(1200,1200,title='Stand The Fight | 260 mm shirt artwork')
    fit(clothing,logos['english'],75,95,1050,1010)
    clothing.export(ROOT/'patches/stf-shirt-front-260mm',png_width=2400,physical=(260/25.4*72,260/25.4*72))
    return scenes
