import time,re,json,requests,io,random,subprocess
import numpy as np
from PIL import Image, ImageFilter
from scipy import ndimage
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service
o=Options(); o.set_preference('dom.webdriver.enabled',False)
o.set_preference('network.proxy.type',2); o.set_preference('network.proxy.autoconfig_url','http://127.0.0.1:9999/proxy.pac')
d=webdriver.Firefox(service=Service('./gd0371/geckodriver'), options=o)
def xdo(*a): subprocess.run(['xdotool',*map(str,a)],check=False)
try:
    d.set_window_position(0,0); d.set_window_size(1000,820)
    d.get('http://127.0.0.1:9999/geetest_page.html')
    for _ in range(60):
        time.sleep(0.5)
        if d.execute_script("return document.querySelectorAll('.geetest_bg').length>0"): break
    time.sleep(1.5)
    info=d.execute_script("""function r(s){var e=document.querySelector(s);if(!e)return null;var b=e.getBoundingClientRect();return {t:b.top,l:b.left,w:b.width,h:b.height,bg:getComputedStyle(e).backgroundImage};}return {bg:r('.geetest_bg'),slice:r('.geetest_slice'),slicebg:r('.geetest_slice_bg'),btn:r('.geetest_btn'),sx:window.mozInnerScreenX,sy:window.mozInnerScreenY};""")
    if not info.get('bg'): print('no captcha'); raise SystemExit
    def dl(u):
        m=re.search(r'url\("?([^")]+)"?\)',u or '');return requests.get(m.group(1).replace('http://','https://'),timeout=20,verify=False).content
    bg=Image.open(io.BytesIO(dl(info['bg']['bg']))).convert('RGB'); sl=Image.open(io.BytesIO(dl(info['slicebg']['bg']))).convert('RGBA')
    g=np.array(bg.convert('L')).astype(np.float32); sa=np.array(sl); mask=sa[:,:,3]>128
    ys,xs=np.where(mask); ax0,ay0=xs.min(),ys.min(); aw,ah=xs.max()-ax0+1,ys.max()-ay0+1
    top=int(round((info['slice']['t']-info['bg']['t'])*bg.size[1]/info['bg']['h'])); top=max(0,min(bg.size[1]-ah,top))
    edges=np.array(bg.convert('L').filter(ImageFilter.FIND_EDGES)).astype(np.float32)
    contour=ndimage.binary_dilation(mask)&~ndimage.binary_erosion(mask)
    dark=g<100; e_s=[];i_s=[];d_s=[]
    for x in range(0,bg.size[0]-aw-ax0+1):
        reg=g[top:top+ah,x+ax0:x+ax0+aw]; m2=mask[ay0:ay0+ah,ax0:ax0+aw]
        e_s.append((edges[top:top+ah,x+ax0:x+ax0+aw][contour[ay0:ay0+ah,ax0:ax0+aw]].mean(),x))
        i_s.append((((dark[top:top+ah,x+ax0:x+ax0+aw]&m2).sum()/m2.sum()),x))
        d_s.append((reg[m2].mean(),x))
    ex=max(e_s)[1]; ix=max(i_s)[1]; dx=min(d_s)[1]; x=sorted([ex,ix,dx])[1]
    scale=info['bg']['w']/bg.size[0]; D=x*scale
    print('edge',ex,'iou',ix,'dark',dx,'chosen',x,'D',D)
    X=int(info['sx']+info['btn']['l']+info['btn']['w']/2); Y=int(info['sy']+info['btn']['t']+info['btn']['h']/2)
    xdo('mousemove',X,Y); time.sleep(0.3); xdo('mousedown',1); time.sleep(0.2)
    n=42; 
    for i in range(1,n+1):
        t=i/n; p=1-(1-t)**3
        xdo('mousemove',int(X+D*p),Y); time.sleep(random.uniform(0.015,0.035))
    time.sleep(0.2); xdo('mouseup',1); time.sleep(5)
    print('validate',d.execute_script('return window.validateResult'))
    print('res',d.execute_script("var e=document.querySelector('.geetest_result');return e?e.innerText:null"))
finally: d.quit()
