"""Verify white grab dots render when long-press is armed near an endpoint,
and that copy-drag from the tag still works after the endpoint changes."""
import sys, time
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service

opts = Options()
svc = Service(executable_path="geckodriver.exe")
d = webdriver.Firefox(options=opts, service=svc)
d.set_window_size(480, 900)

try:
    d.get("http://localhost:8000/field-capture.html?debug")
    time.sleep(2)
    d.execute_script('document.querySelector("[data-action=newjob]").click()')
    time.sleep(0.6)
    d.execute_script('document.querySelector("[data-action=opensketch]").click()')
    time.sleep(0.6)
    d.execute_script("""
        const T = window.__test;
        const job = T.state.jobs[0]; const sk = job.sketches[0];
        const c = document.createElement('canvas'); c.width=200; c.height=150;
        const ctx = c.getContext('2d'); ctx.fillStyle='#ccc'; ctx.fillRect(0,0,200,150);
        sk.photo = { dataUrl: c.toDataURL('image/jpeg', 0.8), width: 200, height: 150 };
        T.saveState();
    """)
    d.execute_script(
        "const T=window.__test; T.ui.screen='sketch'; T.ui.sketchId=T.state.jobs[0].sketches[0].id; T.render();"
    )
    time.sleep(0.6)
    d.execute_script("""
        const canvas = document.getElementById('sketchCanvas');
        canvas.setPointerCapture = function(){};
        canvas.releasePointerCapture = function(){};
        canvas.hasPointerCapture = function(){ return false; };
        const shell = document.querySelector('.sketch-shell');
        const sr = shell.getBoundingClientRect();
        const left = sr.left + shell.clientLeft, top = sr.top + shell.clientTop;
        const view = document.getElementById('sketchView');
        const T = window.__test;
        const v = T.ui.viewState[T.ui.sketchId] || { scale: 1, tx: 0, ty: 0 };
        const w = view.offsetWidth, h = view.offsetHeight;
        const opts = { bubbles: true, cancelable: true, pointerType: 'touch', isPrimary: true };
        const s = { x: left + v.tx + 0.2*w*v.scale, y: top + v.ty + 0.3*h*v.scale }, e = { x: left + v.tx + 0.5*w*v.scale, y: top + v.ty + 0.4*h*v.scale };
        canvas.dispatchEvent(new PointerEvent('pointerdown', Object.assign({}, opts, {pointerId: 5, clientX: s.x, clientY: s.y})));
        for (let i = 1; i <= 4; i++) canvas.dispatchEvent(new PointerEvent('pointermove', Object.assign({}, opts, {pointerId: 5, clientX: s.x+(e.x-s.x)*i/4, clientY: s.y+(e.y-s.y)*i/4})));
        canvas.dispatchEvent(new PointerEvent('pointerup', Object.assign({}, opts, {pointerId: 5, clientX: e.x, clientY: e.y})));
    """)
    time.sleep(0.5)
    d.execute_script('document.querySelector(".sheet-minimal [data-action=closesheet]").click()')
    time.sleep(0.4)

    # Hold on the START endpoint (0.2, 0.3). While holding, check longPress
    # state and that the dots render (canvas has white pixels at endpoints).
    d.execute_script("""
        const canvas = document.getElementById('sketchCanvas');
        canvas.setPointerCapture = function(){};
        canvas.releasePointerCapture = function(){};
        canvas.hasPointerCapture = function(){ return false; };
        const shell = document.querySelector('.sketch-shell');
        const sr = shell.getBoundingClientRect();
        const left = sr.left + shell.clientLeft, top = sr.top + shell.clientTop;
        const view = document.getElementById('sketchView');
        const T = window.__test;
        const v = T.ui.viewState[T.ui.sketchId] || { scale: 1, tx: 0, ty: 0 };
        const w = view.offsetWidth, h = view.offsetHeight;
        const mx = left + v.tx + 0.2 * w * v.scale;
        const my = top + v.ty + 0.3 * h * v.scale;
        const opts = { bubbles: true, cancelable: true, pointerType: 'touch', isPrimary: true };
        canvas.dispatchEvent(new PointerEvent('pointerdown', Object.assign({}, opts, {pointerId: 6, clientX: mx, clientY: my})));
    """)
    time.sleep(0.6)
    print("longPress:", d.execute_script(
        "return JSON.stringify(window.__test.ui.longPress ? {mode: window.__test.ui.longPress.mode, ready: window.__test.ui.longPress.ready, endpoint: window.__test.ui.longPress.endpoint} : null);"
    ))
    # Check white pixels near the two endpoints on the canvas
    print("dots:", d.execute_script("""
        const canvas = document.getElementById('sketchCanvas');
        const ctx = canvas.getContext('2d');
        const view = document.getElementById('sketchView');
        const w = view.offsetWidth, h = view.offsetHeight;
        const ratio = canvas.width / w;
        const px = (lx, ly) => ctx.getImageData(Math.round(lx*w*ratio), Math.round(ly*h*ratio), 1, 1).data;
        const s = px(0.2, 0.3), e = px(0.5, 0.4);
        return JSON.stringify({startPx: [s[0],s[1],s[2]], endPx: [e[0],e[1],e[2]]});
    """))
    # Release without moving -> modal should open
    print("release:", d.execute_script("""
        const canvas = document.getElementById('sketchCanvas');
        const T = window.__test;
        const shell = document.querySelector('.sketch-shell');
        const sr = shell.getBoundingClientRect();
        const left = sr.left + shell.clientLeft, top = sr.top + shell.clientTop;
        const view = document.getElementById('sketchView');
        const v = T.ui.viewState[T.ui.sketchId] || { scale: 1, tx: 0, ty: 0 };
        const w = view.offsetWidth, h = view.offsetHeight;
        const mx = left + v.tx + 0.2 * w * v.scale;
        const my = top + v.ty + 0.3 * h * v.scale;
        const opts = { bubbles: true, cancelable: true, pointerType: 'touch', isPrimary: true };
        canvas.dispatchEvent(new PointerEvent('pointerup', Object.assign({}, opts, {pointerId: 6, clientX: mx, clientY: my})));
        return JSON.stringify({pinModal: T.ui.pinModal});
    """))
    time.sleep(0.3)
    d.execute_script('document.querySelector(".sheet [data-action=closesheet]").click()')
    time.sleep(0.3)

    # Copy-drag from TAG still works: tag is at midpoint (0.35, 0.35)
    d.execute_script("""
        const canvas = document.getElementById('sketchCanvas');
        canvas.setPointerCapture = function(){};
        canvas.releasePointerCapture = function(){};
        canvas.hasPointerCapture = function(){ return false; };
        const shell = document.querySelector('.sketch-shell');
        const sr = shell.getBoundingClientRect();
        const left = sr.left + shell.clientLeft, top = sr.top + shell.clientTop;
        const view = document.getElementById('sketchView');
        const T = window.__test;
        const v = T.ui.viewState[T.ui.sketchId] || { scale: 1, tx: 0, ty: 0 };
        const w = view.offsetWidth, h = view.offsetHeight;
        const mx = left + v.tx + 0.35 * w * v.scale;
        const my = top + v.ty + 0.35 * h * v.scale;
        const ex = left + v.tx + 0.55 * w * v.scale;
        const ey = top + v.ty + 0.45 * h * v.scale;
        const opts = { bubbles: true, cancelable: true, pointerType: 'touch', isPrimary: true };
        canvas.dispatchEvent(new PointerEvent('pointerdown', Object.assign({}, opts, {pointerId: 7, clientX: mx, clientY: my})));
    """)
    time.sleep(0.6)
    d.execute_script("""
        const canvas = document.getElementById('sketchCanvas');
        const shell = document.querySelector('.sketch-shell');
        const sr = shell.getBoundingClientRect();
        const left = sr.left + shell.clientLeft, top = sr.top + shell.clientTop;
        const view = document.getElementById('sketchView');
        const T = window.__test;
        const v = T.ui.viewState[T.ui.sketchId] || { scale: 1, tx: 0, ty: 0 };
        const w = view.offsetWidth, h = view.offsetHeight;
        const mx = left + v.tx + 0.35 * w * v.scale;
        const my = top + v.ty + 0.35 * h * v.scale;
        const ex = left + v.tx + 0.55 * w * v.scale;
        const ey = top + v.ty + 0.45 * h * v.scale;
        const opts = { bubbles: true, cancelable: true, pointerType: 'touch', isPrimary: true };
        for (let i = 1; i <= 5; i++) canvas.dispatchEvent(new PointerEvent('pointermove', Object.assign({}, opts, {pointerId: 7, clientX: mx+(ex-mx)*i/5, clientY: my+(ey-my)*i/5})));
        canvas.dispatchEvent(new PointerEvent('pointerup', Object.assign({}, opts, {pointerId: 7, clientX: ex, clientY: ey})));
    """)
    time.sleep(0.3)
    print("lines after copy-drag:", d.execute_script("""
        const T=window.__test; const sk=T.state.jobs[0].sketches[0];
        return JSON.stringify(sk.lines.map(l => ({num: l.num, start: l.start, end: l.end})));
    """))
finally:
    d.quit()