from pyscript import document
from pyodide.ffi import create_proxy

document.getElementById("shape-options").style.display = "flex"

image = document.getElementById("annotation-image")
zone = document.getElementById("annotation-zone")
confirm_button = document.getElementById("annotation-confirm")
cancel_button = document.getElementById("annotation-cancel")

confirm_button.style.display = "none"
cancel_button.style.display = "none"

shape_type = ""
bbox_pos = None
new_shape = None


def follow_cursor(event):
    rect = zone.getBoundingClientRect()
    x = event.clientX - rect.left
    y = event.clientY - rect.top
    vertical_ruler.style.left = str(x) + "px"
    horizontal_ruler.style.top = str(y) + "px"


# These are functions usable in JS
cancel_bbox_proxy = create_proxy(lambda event: cancel_bbox(event))
make_bbox_proxy = create_proxy(lambda event: make_bbox(event))
follow_cursor_proxy = create_proxy(follow_cursor)


def switch_shape(event):
    global shape_type
    shape = event.currentTarget.id
    shape_type = shape
    print("Shape is now of type:", shape)

vertical_ruler = document.getElementById("annotation-ruler-vertical")
horizontal_ruler = document.getElementById("annotation-ruler-horizontal")
vertical_ruler_2 = document.getElementById("annotation-ruler-vertical-secondary")
horizontal_ruler_2 = document.getElementById("annotation-ruler-horizontal-secondary")
helper_message = document.getElementById("annotation-helper-message")

helper_message.innerText = "Select a shape type then click on the image to begin defining it"


def cancel_bbox(event):
    global bbox_pos, new_shape

    if new_shape is not None and event is not None:
        # Require event so the shape is kept when it ends normally
        new_shape.remove()
        new_shape = None
    zone.removeEventListener("click", make_bbox_proxy)
    document.removeEventListener("keydown", cancel_bbox_proxy)
    cancel_button.removeEventListener("click", cancel_bbox_proxy)

    bbox_pos = None
    vertical_ruler.style.display = "none"
    horizontal_ruler.style.display = "none"
    vertical_ruler_2.style.display = "none"
    horizontal_ruler_2.style.display = "none"
    document.body.style.cursor = "auto"
    cancel_button.style.display = "none"
    helper_message.innerText = "Select a shape type then click on the image to begin defining it"

def make_bbox(event):
    global new_shape, bbox_pos
    zone_rect = zone.getBoundingClientRect()

    if bbox_pos is None:
        helper_message.innerText = "Now define the second point"

        bbox_pos = [(event.clientX - zone_rect.left) / zone_rect.width,
                    (event.clientY - zone_rect.top) / zone_rect.height]
        vertical_ruler_2.style.left = str(bbox_pos[0] * 100) + "%"
        horizontal_ruler_2.style.top = str(bbox_pos[1] * 100) + "%"
        vertical_ruler_2.style.display = "block"
        horizontal_ruler_2.style.display = "block"

    else:
        x0, y0 = bbox_pos.copy()
        x1 = (event.clientX - zone_rect.left) / zone_rect.width
        y1 = (event.clientY - zone_rect.top) / zone_rect.height

        rectangle = document.createElementNS("http://www.w3.org/2000/svg", "rect")

        new_shape.appendChild(rectangle)
        zone.appendChild(new_shape)

        minx = min(x0, x1)
        miny = min(y0, y1)
        maxx = max(x0, x1)
        maxy = max(y0, y1)

        rectangle.setAttribute("x", str(minx * image.naturalWidth))
        rectangle.setAttribute("y", str(miny * image.naturalHeight))
        rectangle.setAttribute("width", str((maxx - minx) * image.naturalWidth))
        rectangle.setAttribute("height", str((maxy - miny) * image.naturalHeight))
        rectangle.setAttribute("fill", "none")
        rectangle.classList.add("shape-bbox")

        cancel_bbox(None)

def open_shape(event):
    global new_shape, bbox_pos
    if bbox_pos:
        return
    print("Creating a new shape of type:", shape_type)
    new_shape = document.createElementNS("http://www.w3.org/2000/svg", "svg")
    new_shape.setAttribute("width", "100%")
    new_shape.setAttribute("height", "100%")
    zone_rect = zone.getBoundingClientRect()
    new_shape.setAttribute("viewBox", f"0 0 {image.naturalWidth} {image.naturalHeight}")

    if shape_type == "shape-bbox":
        helper_message.innerText = ("Define the first point at the intersection of the lines "
                                    "by clicking on the image, or click the cross to cancel")

        cancel_button.addEventListener("click", cancel_bbox_proxy)
        document.addEventListener("keydown", cancel_bbox_proxy)
        cancel_button.style.display = "block"
        bbox_pos = None
        zone.addEventListener("click", make_bbox_proxy)
        vertical_ruler.style.display = "block"
        horizontal_ruler.style.display = "block"
        document.body.style.cursor = "crosshair"


for button in list(document.getElementById("shape-selector").children):
    button.addEventListener("click", create_proxy(switch_shape))
    print("Shape", button.id, "is available")


zone.addEventListener("mousemove", follow_cursor_proxy)
zone.addEventListener("click", create_proxy(open_shape))
