//! By convention, root.zig is the root source file when making a library.
const std = @import("std");

pub const platform = @import("platform.zig");

const TILE_SIZE = 32;

const V2 = struct {
    x: f32,
    y: f32,

    fn add(self: V2, other: V2) V2 {
        return .{
            .x = self.x + other.x,
            .y = self.y + other.y,
        };
    }

    fn sub(self: V2, other: V2) V2 {
        return .{
            .x = self.x - other.x,
            .y = self.y - other.y,
        };
    }
};

const Camera = struct {
    pos: V2,
    offset: V2,
};

const Brick = struct {
    pos: V2,
    tiles: [4][4]u32,
};

const State = struct {
    frame_count: i32,
    mouse_pos: V2,
    camera: Camera,
};

fn fillRect(
    buffer: platform.OffscreenBuffer,
    x: i32,
    y: i32,
    width: i32,
    height: i32,
    color: u32,
) void {
    var pixels: []u32 = @ptrCast(@alignCast(buffer.data));

    const start_x: usize = @intCast(x);
    const end_x: usize = @intCast(x + width);
    const start_y: usize = @intCast(y);
    const end_y: usize = @intCast(y + height);

    for (start_y..end_y) |i| {
        for (start_x..end_x) |j| {
            const idx: usize = i * @as(usize, @intCast(buffer.width)) + j;

            pixels[idx] = color;
        }
    }
}

fn fillSquare(
    buffer: platform.OffscreenBuffer,
    x: i32,
    y: i32,
    size: i32,
    color: u32,
) void {
    fillRect(buffer, x, y, size, size, color);
}

pub fn updateAndRender(memory: *platform.AppMemory, buffer: platform.OffscreenBuffer, input: platform.AppInput) void {
    var state: *State = @ptrCast(@alignCast(memory.permanent_storage));

    if (!memory.initialized) {
        state.camera.offset.x = @floatFromInt(@divTrunc(buffer.width, 2));
        state.camera.offset.y = @floatFromInt(@divTrunc(buffer.height, 2));

        state.camera.pos = state.camera.pos.add(state.camera.offset);

        memory.initialized = true;
    }

    // Update
    const mouse_pos = V2{ .x = @floatCast(input.mouse_x), .y = @floatCast(input.mouse_y) };

    if (input.mouse_left_down) {
        const diff = mouse_pos.sub(state.mouse_pos);
        state.camera.pos = state.camera.pos.add(diff);
    }

    state.mouse_pos = mouse_pos;

    const brick = Brick{
        .pos = V2{ .x = 50, .y = 50},
        .tiles = [4][4]u32{
            .{1, 1, 1, 1},
            .{1, 0, 0, 0},
            .{0, 0, 0, 0},
            .{0, 0, 0, 0},
        },
    };

    // Render
    fillRect(buffer, 0, 0, buffer.width, buffer.height, 0xFFFFFFFF);

    const board_pos = V2{ .x = 64, .y = 64 };
    for (0..7) |i| {
        for (0..7) |j| {
            if (i == 0 and j == 6) continue;
            if (i == 1 and j == 6) continue;
            if (i == 6 and j == 3) continue;
            if (i == 6 and j == 4) continue;
            if (i == 6 and j == 5) continue;
            if (i == 6 and j == 6) continue;

            const tile_pos = V2{
                .x = @floatFromInt(j * TILE_SIZE),
                .y = @floatFromInt(i * TILE_SIZE),
            };
            const camera_pos = board_pos.add(tile_pos).add(state.camera.pos);
            fillSquare(buffer, @intFromFloat(camera_pos.x), @intFromFloat(camera_pos.y), 30, 0xFF000000);
        }
    }

    for (brick.tiles, 0..) |row, i| {
        for (row, 0..) |tile, j| {
            if (tile == 1) {
                const pos = V2{
                    .x = @floatFromInt(j * TILE_SIZE + 8),
                    .y = @floatFromInt(i * TILE_SIZE + 8),
                };
                const camera_pos = brick.pos.add(pos).add(state.camera.pos);
                fillSquare(buffer, @intFromFloat(camera_pos.x), @intFromFloat(camera_pos.y), 30, 0xFFFF0000);
            }

        }
    }

    state.frame_count += 1;
}

