#import "Basic";
#import "File";
#import "Sort";
#import "String";

solve_day7 :: (test: bool) {
    contents := read_entire_file("inputs/day7.txt");
    lines    := split(contents, "\n");

    hands: [..]Hand;

    for line: lines {
        split_line := split(line, " ");

        bid := string_to_int(split_line[1], 10, u64);

        array_add(*hands, .{
            cards = split_line[0],
            score = calc_score_part1(split_line[0]),
            score2 = calc_score_part2(split_line[0]),
            bid = bid,
        });
    }

    part1 := 0;
    part2 := 0;

    bubble_sort(hands, compare_hands_part1);
    //array_reserve(*hands, hands.count);

    for hands {
        part1 += cast(s64)(it_index + 1) * cast(s64)it.bid;
    }

    quick_sort(hands, compare_hands_part2);

    for hands {
        part2 += cast(s64)(it_index + 1) * cast(s64)it.bid;
    }

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

}

calc_score_part1 :: (cards: string) -> u32 {
    index := "23456789TJQKA";
    count: [13]u8;

    for 0..cards.count - 1 {
        count[find_index_from_left(index, cards[it])] += 1;
    }

    quick_sort(count, (a, b) => cast(s64)b - cast(s64)a);

    c: u32 = 0;

    if count[0] == {
        case 5;
            c = 10;
        case 4;
            c = 9;
        case 3;
            if count[1] == 2  c = 8;
            else              c = 7;
        case 2;
            if count[1] == 2  c = 6;
            else              c = 5;
        case;
    }

    return c;
}

calc_score_part2 :: (cards: string) -> u32 {
    index := "J23456789TQKA";
    count: [13]u8;

    for 0..cards.count - 1 {
        count[find_index_from_left(index, cards[it])] += 1;
    }

    joker_count := count[0];
    count[0] = 0;

    quick_sort(count, (a, b) => cast(s64)b - cast(s64)a);

    count[0] += joker_count;

    c: u32 = 0;

    if count[0] == {
        case 5;
            c = 10_000;
        case 4;
            c = 9_000;
        case 3;
            if count[1] == 2  c = 8_000;
            else              c = 7_000;
        case 2;
            if count[1] == 2  c = 6_000;
            else              c = 5_000;
        case;
    }

    return c;
}

compare_hands_part1 :: (h1: Hand, h2: Hand) -> s64 {
    index := "23456789TJQKA";
    if h1.score == h2.score {
        for 0..h1.cards.count - 1 {
            if h1.cards[it] == h2.cards[it]  continue;

            return find_index_from_left(index, h1.cards[it]) - find_index_from_left(index, h2.cards[it]);
        }
    }
    return cast(s64)h1.score - cast(s64)h2.score;
}

compare_hands_part2 :: (h1: Hand, h2: Hand) -> s64 {
    index := "J23456789TQKA";
    if h1.score2 == h2.score2 {
        for 0..h1.cards.count - 1 {
            if h1.cards[it] == h2.cards[it]  continue;

            return find_index_from_left(index, h1.cards[it]) - find_index_from_left(index, h2.cards[it]);
        }
    }
    return cast(s64)h1.score2 - cast(s64)h2.score2;
}

Hand :: struct {
    bid:    u64;
    score:  u64;
    score2: u64;
    cards:  string;
}