import json,os,re,sys,time,urllib.request,urllib.parse,hashlib
OUT=sys.argv[1]; os.makedirs(OUT+"/pics",exist_ok=True)
H={"User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:131.0) Gecko/20100101 Firefox/131.0","Referer":"https://tds.fandom.com/"}
def get(u):
    for i in range(5):
        try: return urllib.request.urlopen(urllib.request.Request(u,headers=H),timeout=60).read()
        except Exception as e:
            if i==4 or getattr(e,"code",0)==404: raise
            time.sleep(3*(i+1))
def api(**p):
    p["format"]="json"; return json.loads(get("https://tds.fandom.com/api.php?"+urllib.parse.urlencode(p)))
def members(cat):
    r=[];c={}
    while True:
        d=api(action="query",list="categorymembers",cmtitle="Category:"+cat,cmlimit=500,cmnamespace=0,**c)
        r+=[m["title"] for m in d["query"]["categorymembers"]]
        if "continue" not in d: return r
        c=d["continue"]
def infobox(t):
    m=re.search(r"\{\{\s*(TowerInfobox|Zombie|Enemy[^|\n]*|[A-Za-z ]*Infobox)\s*\n?\|",t)
    if not m: return None,{}
    i=m.start()+2;depth=1;j=i
    while j<len(t) and depth:
        if t.startswith("{{",j): depth+=1;j+=2
        elif t.startswith("}}",j): depth-=1;j+=2
        else: j+=1
    body=t[m.end()-1:j-2]
    f={};depth=0;cur=""
    parts=[];k=0
    while k<len(body):
        if body.startswith(("{{","[["),k): depth+=1;cur+=body[k:k+2];k+=2;continue
        if body.startswith(("}}","]]"),k): depth-=1;cur+=body[k:k+2];k+=2;continue
        if body[k]=="|" and depth==0: parts.append(cur);cur="";k+=1;continue
        cur+=body[k];k+=1
    parts.append(cur)
    for p in parts:
        if "=" in p:
            a,b=p.split("=",1); f[a.strip()]=b.strip()
    return m.group(1),f
def clean(v):
    v=re.sub(r"\{\{Attr\|([^|}]*)\|([^}]*)\}\}",r"\2",v)
    v=re.sub(r"\{\{Attr\|([^|}]*)\}\}",r"\1 immune",v)
    v=re.sub(r"\{\{(?:Money|Gem|Level|Color\|[^|]*)\|([^}]*)\}\}",r"\1",v)
    v=re.sub(r"\[\[File:[^\]]*\]\]","",v)
    v=re.sub(r"\[\[(?:[^|\]]*\|)?([^\]]*)\]\]",r"\1",v)
    v=re.sub(r"<br\s*/?>"," / ",v); v=re.sub(r"<[^>]+>","",v); v=re.sub(r"\{\{[^}]*\}\}","",v)
    return re.sub(r"\s+"," ",v).strip(" /")
def yes(v):
    v=clean(v).lower()
    return bool(v) and not v.startswith(("no","n/a","none","false","-"))
towers=members("Towers"); enemies=members("Enemies")
hist=set(members("Historical Content")); bosses=set(members("Bosses"))
cats={}
for c in ["Early-Game","Mid-Game","Late-Game","Golden","Hardcore","Exclusive Content","Unreleased Content","Sandbox Only"]:
    try: cats[c]=set(members(c))
    except Exception: cats[c]=set()
items=[]
def chunks(l,n): 
    for i in range(0,len(l),n): yield l[i:i+n]
for kind,lst in (("tower",towers),("enemy",enemies)):
    for ch in chunks(lst,40):
        d=api(action="query",prop="revisions|pageimages",rvprop="content",rvslots="main",piprop="thumbnail",pithumbsize=160,titles="|".join(ch),redirects=1)
        for p in d["query"]["pages"].values():
            if "revisions" not in p: continue
            t=p["revisions"][0]["slots"]["main"]["*"]
            tpl,f=infobox(t)
            if not f: continue
            name=p["title"]; it={"n":name,"k":kind,"tags":[]}
            img=p.get("thumbnail",{}).get("source")
            st=f.get("image-static","").strip()
            if kind=="tower" and st:
                try:
                    ii=api(action="query",prop="imageinfo",iiprop="url",iiurlwidth=200,titles="File:"+st)
                    img=list(ii["query"]["pages"].values())[0]["imageinfo"][0]["thumburl"]
                except Exception as e: print("static",name if False else p["title"],e)
            if img:
                fn=hashlib.md5(img.encode()).hexdigest()[:16]+".png"
                if not os.path.exists(OUT+"/pics/"+fn):
                    try: open(OUT+"/pics/"+fn,"wb").write(get(img))
                    except Exception as e: print("img",name,e); fn=None
                it["img"]=fn and "pics/"+fn
            if kind=="tower":
                for key,tag in (("hidden_detection","Hidden"),("lead_detection","Lead"),("flying_detection","Flying")):
                    if yes(f.get(key,"")): it["tags"].append(tag); it[tag]=clean(f[key])
                for key in ("role","placement","basecost","basedamage","damagetype","basefirerate","baserange","unlockcost","immune"):
                    if f.get(key): it[key]=clean(f[key])
                if it.get("role"): it["tags"]+= [{"Offensive":"Offense"}.get(r.strip(),r.strip()) for r in re.split(r"[/,]",it["role"]) if r.strip()]
                if it.get("placement"): it["tags"]+= [r.strip() for r in re.split(r"[/,]",it["placement"]) if r.strip() in ("Ground","Cliff","Hybrid")]
            else:
                for key,tag in (("hidden","Hidden"),("fly","Flying"),("lead","Lead"),("ghost","Ghost")):
                    if yes(f.get(key,"")): it["tags"].append(tag)
                for key in ("base_hp","speed","immunity","mode_appearance","first_wave_appearance","spawned_by"):
                    if f.get(key): it[key]=clean(f[key])[:200]
                if name in bosses or "boss" in name.lower(): it["tags"].append("Boss")
                imm=it.get("immunity","").lower()
                for w,tag in (("freeze","Freeze immune"),("burn","Burn immune"),("stun","Stun immune"),("splash","Splash immune"),("full","Full immune")):
                    if w in imm: it["tags"].append(tag)
            if name in hist: it["tags"].append("Removed")
            for c,s in cats.items():
                if name in s: it["tags"].append(c)
            it["tags"]=sorted(set(it["tags"]))
            items.append(it)
        print(kind,len(items),flush=True)
json.dump(items,open(OUT+"/data.json","w"),ensure_ascii=False)
# attribute icons
for a,fn in (("Hidden","HiddenDetection.png"),("Flying","Fly.png"),("Lead","LeadIcon.png"),("Ghost","GhostImmunity.png"),("Boss","BossIcon.png"),("Freeze immune","Freeze.png"),("Burn immune","Fire.png"),("Stun immune","Energy.png"),("Splash immune","Explosion.png"),("Full immune","FullImmunity.png")):
    d=api(action="query",prop="imageinfo",iiprop="url",titles="File:"+fn)
    u=list(d["query"]["pages"].values())[0]["imageinfo"][0]["url"]
    open(OUT+"/pics/attr-"+a.split()[0].lower()+".png","wb").write(get(u))
print("KLART",len(items))
