#import "String";
solve_day8 :: (test: bool) {
    contents := read_entire_file(ifx test then "inputs/day8_test.txt" else "inputs/day8.txt");

    lines := split(contents, "\n");

    builder: String_Builder;

    part1 := 0;
    part2 := 0;

    grid: Grid = .{
        width = lines[0].count,
        height = lines.count,
    };

    for line: lines {
        print_to_builder(*builder, line);
    }

    grid.grid = builder_to_string(*builder);
    seeable: []u8 = NewArray(grid.grid.count, u8);
    defer array_free(seeable);

    mark_grid(grid, seeable);
    transpose(grid);
    transpose(seeable, grid.width, grid.height);
    mark_grid(grid, seeable);
    transpose(grid);

    for 0..seeable.count - 1 {
        if seeable[it] > 0 {
            part1 += 1;
        }
    }

    part1 += (grid.width - 1) * 4;

    for x: 1..grid.width - 2 {
        for y: 1..grid.height - 2 {
            part2 = max(part2, scenic_score(x, y, grid));
        }
    }

    print("Part 1: %\n", part1);
    print("Part 2: %\n", part2);

}

scenic_score :: (x: s64, y: s64, grid: Grid) -> s64 {
    // Up
    tree_height := grid.grid[y * grid.width + x];
    up_score    := 0;
    down_score  := 0;
    right_score := 0;
    left_score  := 0;

    for < x - 1..0 {
        left_score += 1;
        if grid.grid[y * grid.width + it] >= tree_height {
            break;
        }
    }
    for x + 1..grid.width - 1 {
        right_score += 1;
        if grid.grid[y * grid.width + it] >= tree_height {
            break;
        }
    }

    for < y - 1..0 {
        up_score += 1;
        if grid.grid[it * grid.width + x] >= tree_height {
            break;
        }
    }
    for y + 1..grid.height - 1 {
        down_score += 1;
        if grid.grid[it * grid.width + x] >= tree_height {
            break;
        }
    }

    return up_score * down_score * left_score * right_score;
}

mark_grid :: (grid: Grid, seeable: []u8) {
    for y: 1..grid.height - 2 {
        current_height_backward := grid.grid[y * grid.width + grid.width - 1];
        current_height_forward  := grid.grid[y * grid.width];
        for x: 1..grid.width - 2 {
            if grid.grid[y * grid.width + x] > current_height_forward {
                seeable[y * grid.width + x] = 1;
                current_height_forward = grid.grid[y * grid.width + x];
            }
            if grid.grid[y * grid.width + grid.width - x - 1] > current_height_backward {
                seeable[y * grid.width + grid.width - x - 1] = 1;
                current_height_backward = grid.grid[y * grid.width + grid.width - x - 1];
            }
        }
    }
}

transpose :: (grid: []u8, width: s64, height: s64) {
    for x: 0..width - 1 {
        for y: x..height - 1 {
            grid[y * width + x], grid[x * height + y] = grid[x * height + y], grid[y * width + x];
        }
    }
}

transpose :: (grid: Grid) {
    for x: 0..grid.width - 1 {
        for y: x..grid.height - 1 {
            grid.grid[y * grid.width + x], grid.grid[x * grid.height + y] = grid.grid[x * grid.height + y], grid.grid[y * grid.width + x];
        }
    }
}