import matrix
import shared
import itertools
import functools


def part1(rows):
    groups = [list(v) for k, v in itertools.groupby(rows, key=lambda x: not x) if not k]

    indexes = []
    for idx, (left, right) in enumerate(groups):
        left = eval(left)
        right = eval(right)
        # print(f"== Pair {idx+1} ==")
        passes = check_group(left, right)
        if passes:
            indexes.append(idx + 1)
        # if passes is True:
        #     print(f"{idx+1} {matrix.colors.GREEN}{passes}{matrix.colors.ENDC}")
        # elif passes is False:
        #     print(f"{idx+1} {matrix.colors.RED}{passes}{matrix.colors.ENDC}")
        # else:
        #     print(f"{idx+1} {matrix.colors.BLUE}{passes}{matrix.colors.ENDC}")
    print(sum(indexes))


def check_group(left, right):
    if isinstance(left, list) and isinstance(right, list):
        # if both items are lists, loop over both
        for idx in range(min(len(left), len(right))):
            check = check_group(left[idx], right[idx])
            # bubble up the int comparisons, or list length comparisons
            if check is False:
                return False
            elif check is True:
                return True
            # is None, continue on! TALLY HO!
        else:
            # If the left list runs out of items first, the inputs are in the right order.
            if len(left) < len(right):
                return True
            # If the right list runs out of items first, the inputs are not in the right order.
            if len(left) > len(right):
                return False
            # If the lists are the same length and no comparison makes a decision about the order, continue checking the next part of the input.
            return None
    elif isinstance(left, int) and isinstance(right, list):
        # If exactly one value is an integer, convert the integer to a list which contains
        # that integer as its only value, then retry the comparison.
        left = [left]
        return check_group(left, right)
    elif isinstance(left, list) and isinstance(right, int):
        # If exactly one value is an integer, convert the integer to a list which contains
        # that integer as its only value, then retry the comparison.
        right = [right]
        return check_group(left, right)
    else:
        # both ints now
        # If the left integer is lower than the right integer, the inputs are in the right order.
        if left < right:
            return True
        # If the left integer is higher than the right integer, the inputs are not in the right order.
        elif left > right:
            return False
        # Otherwise, the inputs are the same integer; continue checking the next part of the input.
        elif left == right:
            return None


def part2(rows):
    two, six = 0, 0
    rows = [eval(r) for r in rows if r]
    rows.append([[2]])
    rows.append([[6]])

    def cmp(x, y):
        return {
            True: 1,
            False: -1,
        }[check_group(x, y)]

    idx = 0  # ew 1 based lists, jeeeze AoC
    for r in sorted(rows, key=functools.cmp_to_key(cmp), reverse=True):
        idx += 1
        if r == [[2]]:
            two = idx
        if r == [[6]]:
            six = idx
            break  # will come 2nd logically, so we can break here to save time

    print(two * six)


def main():
    rows = shared.load_rows(13)
    with shared.elapsed_timer() as elapsed:
        part1(rows)
        print("🕒", elapsed())
    with shared.elapsed_timer() as elapsed:
        part2(rows)
        print("🕒", elapsed())


if __name__ == "__main__":
    main()
