"""A note's place on the design travels with the note.

The percentages move whenever the page changes height, so a note also
carries an anchor: a mockup element and the point's place inside it. The
server stores it, returns it, and clears it when a note is moved without a
new one, because the old anchor names the spot the note was moved away from.
"""

from tests.conftest import as_user
from tests.test_domain import add_screen_option, make_project

POINT = {"s": "section.faq > h2:nth-of-type(1)", "fx": 0.25, "oy": 18.5}
AREA = {"s": "section.hero > h1", "fx": 0.1, "oy": 4,
        "s2": "section.hero > p", "fx2": 0.9, "oy2": 40}


def _set(anchor):
    """The fields that are set; unused second-corner fields come back null."""
    return None if anchor is None else {k: v for k, v in anchor.items() if v is not None}


def _pin(client, oid, **extra):
    body = {"x_percent": 10, "y_percent": 20, "body_md": "a note", **extra}
    r = client.post(f"/api/options/{oid}/pins", json=body)
    assert r.status_code == 200, r.text
    return r.json()["pin"]


def test_a_note_keeps_its_place_on_the_design(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    as_user(client, "cleo")
    pin = _pin(client, oid, anchor=POINT)
    assert _set(pin["anchor"]) == POINT
    listed = client.get(f"/api/options/{oid}/pins").json()["pins"][0]
    assert _set(listed["anchor"]) == POINT


def test_an_area_needs_both_corners(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    as_user(client, "cleo")
    area = _pin(client, oid, w_percent=30, h_percent=10, anchor=AREA)
    assert _set(area["anchor"]) == AREA
    half = _pin(client, oid, w_percent=30, h_percent=10, anchor=POINT)
    assert half["anchor"] is None  # one corner would move one edge only


def test_moving_a_note_replaces_or_clears_its_anchor(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    as_user(client, "cleo")
    pin = _pin(client, oid, anchor=POINT)
    moved = {"s": "footer > p", "fx": 0.5, "oy": 12}
    r = client.post(f"/api/pins/{pin['pin_id']}/move",
                    json={"x_percent": 50, "y_percent": 90, "anchor": moved})
    assert r.status_code == 200, r.text
    assert _set(client.get(f"/api/options/{oid}/pins").json()["pins"][0]["anchor"]) == moved
    r = client.post(f"/api/pins/{pin['pin_id']}/move",
                    json={"x_percent": 40, "y_percent": 80})
    assert r.status_code == 200, r.text
    assert client.get(f"/api/options/{oid}/pins").json()["pins"][0]["anchor"] is None


def test_an_anchor_is_checked(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    as_user(client, "cleo")
    base = {"x_percent": 1, "y_percent": 1, "body_md": "x"}
    for bad in ({"s": "p", "fx": 1.5, "oy": 5},
                {"s": "p", "fx": 0.5, "oy": -1},
                {"s": "", "fx": 0.5, "oy": 5},
                {"s": "p" * 501, "fx": 0.5, "oy": 5}):
        r = client.post(f"/api/options/{oid}/pins", json={**base, "anchor": bad})
        assert r.status_code == 422, bad
