// Pure geometry of the on-screen board: where the centered 8×8 grid sits inside
// a frame, and the two-way mapping between cells and screen points. Owns no
// rendering and pulls in NO GL/stb imports, so the touch→cell mapping is
// unit-testable headless. BoardView composes this for layout + hit-testing, and
// P5's swap input reuses `point_to_cell` to resolve a tap to a swap endpoint.
#import "modules/std.sx";
#import "modules/math";
#import "modules/ui/types.sx";
#import "board.sx";

BoardLayout :: struct {
    cell_size: f32;
    origin: Point;

    // Center a square 8×8 grid inside the safe-area-inset region of `frame`.
    compute :: (self: *BoardLayout, frame: Frame, safe: EdgeInsets) {
        avail := frame.inset(safe);
        cols : f32 = xx BOARD_COLS;
        board_dim := min(avail.size.width, avail.size.height);
        self.cell_size = board_dim / cols;
        total := self.cell_size * cols;
        self.origin = Point.{
            x = avail.origin.x + (avail.size.width - total) * 0.5,
            y = avail.origin.y + (avail.size.height - total) * 0.5
        };
    }

    cell_frame :: (self: *BoardLayout, col: s64, row: s64) -> Frame {
        Frame.make(
            self.origin.x + xx col * self.cell_size,
            self.origin.y + xx row * self.cell_size,
            self.cell_size,
            self.cell_size
        )
    }

    // Inverse of `cell_frame`: map a view-local point to the grid cell under it,
    // or null when the point falls outside the 8×8 grid. The `< 0.0` guards run
    // BEFORE the truncating cast, since casting a small negative float rounds
    // toward zero into a valid index. Uses the SAME origin / cell_size `compute`
    // produced, so a tap resolves to exactly the cell drawn under the finger.
    point_to_cell :: (self: *BoardLayout, p: Point) -> ?Cell {
        if self.cell_size <= 0.0 { return null; }
        fx := (p.x - self.origin.x) / self.cell_size;
        fy := (p.y - self.origin.y) / self.cell_size;
        if fx < 0.0 or fy < 0.0 { return null; }
        col : s64 = xx fx;
        row : s64 = xx fy;
        if col >= BOARD_COLS or row >= BOARD_ROWS { return null; }
        Cell.{ col = col, row = row }
    }
}
