const std = @import("std");
const ArrayList = std.ArrayList;

pub fn solve_part1(allocator: std.mem.Allocator, file_name: []const u8) !void {
    var inputs = try std.fs.cwd().openFile(file_name, .{});
    var buffered_reader = std.io.bufferedReader(inputs.reader());
    var in_stream = buffered_reader.reader();

    var buffer: [1024]u8 = undefined;

    var numbers = ArrayList(i64).init(allocator);

    var part1_result: i64 = 0;
    var part2_result: i64 = 0;

    while (try in_stream.readUntilDelimiterOrEof(&buffer, '\n')) |line| {
        numbers.clearRetainingCapacity();

        var tokens = std.mem.tokenizeAny(u8, line, "\n ");

        while (tokens.next()) |token| {
            if (token.len > 0) {
                std.log.info("{s}", .{token});
                try numbers.append(try std.fmt.parseInt(i32, token, 10));
            }
        }

        var t = try find_outer_val(allocator, numbers.items);
        std.log.info("Partf: {d}", .{t});
        part1_result += t;

        std.mem.reverse(i64, numbers.items);
        t = try find_outer_val(allocator, numbers.items);
        part2_result += t;
    }

    std.log.info("Part 1: {d}", .{part1_result});
    std.log.info("Part 2: {d}", .{part2_result});
}

fn find_outer_val(allocator: std.mem.Allocator, numbers: []i64) !i64 {
    var next_numbers = try allocator.alloc(i64, numbers.len - 1);
    defer allocator.free(next_numbers);

    var diff = numbers[1] - numbers[0];

    var all_same = true;

    for (0..numbers.len - 1) |i| {
        next_numbers[i] = numbers[i + 1] - numbers[i];

        all_same = all_same and diff == next_numbers[i];
    }

    if (all_same) {
        std.log.info("Partd: {d}", .{diff});
        return diff + numbers[numbers.len - 1];
    } else {
        std.log.info("{d}", .{next_numbers});
    }

    var r = try find_outer_val(allocator, next_numbers);

    std.log.info("Partr: {d}", .{r + numbers[numbers.len - 1]});

    return r + numbers[numbers.len - 1];
}