# -*- coding: utf-8 -*-
"""探测 UE 何时就绪可用"""
import sys, socket, json, time
sys.stdout.reconfigure(encoding='utf-8')
HOST = "localhost"; PORT = 28800
PAGE_ID = "70039F329097C14448996F189E3A42A1"

def ws():
    import urllib.parse
    u = "ws://%s:%s/devtools/page/%s" % (HOST, PORT, PAGE_ID)
    p = urllib.parse.urlparse(u)
    s = socket.create_connection((p.hostname, p.port or 80), timeout=15)
    req = ("GET %s HTTP/1.1\r\nHost: %s:%s\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n" % (p.path, p.hostname, p.port))
    s.send(req.encode())
    resp = b''
    while b'\r\n\r\n' not in resp: resp += s.recv(4096)
    return s

def send(s, d):
    d = d.encode('utf-8'); n = len(d); m = b'\x01\x02\x03\x04'
    if n <= 125: h = bytes([0x81, n|0x80]) + m
    elif n <= 65535: h = bytes([0x81, 0xFE]) + n.to_bytes(2,'big') + m
    else: h = bytes([0x81, 0xFF]) + n.to_bytes(8,'big') + m
    s.send(h + bytes(d[i]^m[i%4] for i in range(n)))

def recv(s):
    def rx(n):
        b = b''
        while len(b) < n: b += s.recv(n-len(b))
        return b
    h = rx(2); n = h[1]&0x7f
    if n == 126: n = int.from_bytes(rx(2),'big')
    elif n == 127: n = int.from_bytes(rx(8),'big')
    return rx(n).decode('utf-8')

_mid = 0
def cdp(s, js, timeout=15):
    global _mid
    _mid += 1
    send(s, json.dumps({'id':_mid,'method':'Runtime.evaluate','params':{'expression':js,'returnByValue':True}}))
    s.settimeout(timeout)
    for _ in range(300):
        try:
            r = json.loads(recv(s))
            if r.get('id') == _mid:
                return r.get('result',{}).get('result',{}).get('value','')
        except: pass
    return ''

s = ws()
print("[OK] Connected\n")

# 每秒探测一次，连续30秒
for i in range(30):
    # 方法1：直接访问 instants[key]
    r1 = cdp(s, "var ins=window.UE_V2&&window.UE_V2.instants;var ks=ins?Object.keys(ins):[];var info={};ks.forEach(function(k){try{var inst=ins[k];info[k]={key:inst.key,hasSetContent:typeof inst.setContent,hasExecCommand:typeof inst.execCommand,hasGetContent:typeof inst.getContent,readyState:!!(inst.iframe||inst.body)}}catch(e){info[k]='err'}});JSON.stringify(info)", timeout=5)
    # 方法2：通过 getEditor
    r2 = cdp(s, "var ge=window.UE_V2&&window.UE_V2.getEditor;if(!ge)return 'no getEditor';var ins=ge('ueditorInstant0');if(!ins)return 'getEditor returned null';var methods=['setContent','execCommand','getContent','addListener','ready'];var out={};methods.forEach(function(m){out[m]=typeof ins[m]});out.bodyOk=!!(ins.body);out.iframeOk=!!(ins.iframe);out.ready=typeof ins.ready;JSON.stringify(out)", timeout=5)
    print(f"[{i+1:02d}s] instants: {r1[:80]} | getEditor: {r2[:100]}")
    if 'setContent:function' in str(r2) or 'hasSetContent:true' in str(r1):
        print("UE ready detected!")
        break
    time.sleep(1)

# 测试 setContent
print("\n[测试 setContent]")
r = cdp(s, "var ins=window.UE_V2&&window.UE_V2.instants;var ks=Object.keys(ins||{});var out='keys:'+ks.join(',');var inst=ins[ks[0]];if(inst){try{inst.setContent('<p><b>测试</b></p>');out+='|setContent ok, len='+inst.getContent().length}catch(e){out+='|err:'+e.message}}else{out+='|inst null'}out", timeout=15)
print(r)

s.close()
