import numpy as np


# TODO: if set to competition mode, get the seed from the api

def set_random_seed(seed: int):
    np.random.seed(seed)


def get_random_number(min: int, max: int):
    return np.random.randint(256 ** 4, dtype='<u4', size=1)[0] % (max - min + 1) + min


class Gamestate:
    def __str__(self) -> str:
        return f"""Seed: {self.seed}
Heu Color: {self.heu_color}
Material Pairs: {self.material_pairs}
Material Zones: {self.materials}
Logistic Plan: {self.logistic_plan}
Logistic Centers: {self.logistic_center}"""

    def __init__(self, seed: int):
        self.seed = seed
        set_random_seed(seed)

        self.heu_color = get_random_number(1, 2)

        self.materials = [0, 0, 0, 0]
        self.material_pairs = []
        for i in range(0, 4):
            num1 = get_random_number(0, 3)
            self.material_pairs.append([num1, num1])
            while self.material_pairs[i][1] == num1:
                self.material_pairs[i][1] = get_random_number(0, 3)

        flat = [item for sublist in self.material_pairs for item in sublist]
        for i in range(0, 4):
            self.materials[i] = flat.count(i)

        self.logistic_plan = [0 for i in range(0, 21)]
        self.logistic_center = [[0, 0, 0, 0] for i in range(0, 4)]
        visited = [5, 5, 5, 5]

        def __logistic_plan_generator(i: int):
            drive_to = get_random_number(0, 3)
            for j in range(0, 4):
                drive_to = (drive_to + j) % 4
                if visited[drive_to] <= 0 or drive_to == self.logistic_plan[i - 1]:
                    continue
                self.logistic_plan[i] = drive_to

                visited[drive_to] -= 1
                finished = True
                for k in visited:
                    if k != 0:
                        finished = False

                if finished and drive_to == 2:
                    visited[drive_to] += 1
                    continue

                if finished:
                    return True

                if i < len(self.logistic_plan):
                    if __logistic_plan_generator(i + 1):
                        return True
                visited[drive_to] += 1
            return False

        self.logistic_plan[0] = 2
        visited[2] -= 1
        _ = __logistic_plan_generator(1)

        self.logistic_plan[-1] = 2
        for i in range(0, len(self.logistic_plan) - 1):
            self.logistic_center[self.logistic_plan[i]][self.logistic_plan[i + 1]] += 1

        self.logistic_plan = [x + 10 for x in self.logistic_plan]

    def get_heuballen(self) -> int:
        return self.heu_color

    def get_logistic_plan(self) -> []:
        return self.logistic_plan

    def get_material_deliveries(self) -> [[]]:
        return self.material_pairs
