// Pure drag → adjacent-swap intent mapping (Phase 5 input). Turns a touch drag —
// a down position and an up/move position, both in the same view-local coordinate
// space BoardLayout uses — into an optional swap intent (A, B): A is the cell
// under the drag start, B its orthogonal neighbour along the drag's dominant axis.
// Owns no rendering and mutates no model, so it is unit-testable headless; P5.2
// feeds the resulting Swap straight into `commit_swap`.
#import "modules/std.sx";
#import "modules/math";
#import "modules/ui/types.sx";
#import "board.sx";
#import "board_layout.sx";

// A drag whose dominant-axis travel is below this fraction of a cell is treated
// as a tap, not a swipe, and yields no intent. Scaling to cell_size keeps the
// feel constant across screen sizes, since the layout sizes cells to the device.
SWIPE_THRESHOLD_FRACTION :f32: 0.5;

// Map a drag to the adjacent-swap intent it expresses, or null when the gesture
// is not a board swipe. Returns null when: the start point is off the board; the
// dominant-axis travel is below the swipe threshold (a tap, not a swipe); or the
// resolved neighbour B would fall off the board. A and B are always orthogonally
// adjacent — the intent never spans more than one cell. The dominant axis is the
// larger of |dx|, |dy| (an exact tie resolves horizontal), and its sign picks the
// direction: +x → right, -x → left, +y → down, -y → up (screen y grows downward,
// matching `cell_frame`). Reuses `point_to_cell` so the start resolves to exactly
// the cell drawn under the finger.
swipe_intent :: (layout: *BoardLayout, start: Point, end: Point) -> ?Swap {
    if a := layout.point_to_cell(start) {
        dx := end.x - start.x;
        dy := end.y - start.y;
        adx := abs(dx);
        ady := abs(dy);

        threshold := layout.cell_size * SWIPE_THRESHOLD_FRACTION;
        if adx < threshold and ady < threshold { return null; }   // a tap, not a swipe

        bcol := a.col;
        brow := a.row;
        if adx >= ady {
            if dx > 0.0 { bcol += 1; } else { bcol -= 1; }
        } else {
            if dy > 0.0 { brow += 1; } else { brow -= 1; }
        }

        if bcol < 0 or bcol >= BOARD_COLS or brow < 0 or brow >= BOARD_ROWS {
            return null;                                          // neighbour off the board
        }

        return Swap.{ a = a, b = Cell.{ col = bcol, row = brow } };
    }
    null                                                          // start off the board
}
