import random as rnd
from coopgame.gameTemplate import GameTemplate
from cooptools.colors import Color
import pygame
from coopgame.renderedObjectHandling.MatrixManipulation import rotateAroundAxis
from coopstructs.geometry.vectors.vectorN import Vector2, VectorN
import numpy as np
import coopgame.handleKeyPressedArgs as hkpa
from coopgame.pygame_k_constant_names import PyKeys, PyMouse

class Particle():
    def __init__(self, id, pos, value, size, color=Color.BLUE):
        self.pos = pos
        self.size = size
        self.thickness = 1
        self.value = value
        self.color = color
        self.id = id

    def __eq__(self, other):
        return self.id == other.id

    def __hash__(self):
        return hash(self.id)

    def display(self, screen: pygame.Surface, color=None):
        if color is None:
            color = self.color
        pygame.draw.circle(screen, color.value, (int(self.pos[0]), int(self.pos[1])), self.size)

class Game(GameTemplate):
    def initialize_game(self):
        pass

    def handle_mouse_scroll_up(self, pressed_keys):
        pass

    def handle_mouse_scroll_down(self, pressed_keys):
        pass

    def sprite_updater(self, delta_time_ms: int):
        pass

    def handle_right_mouse_down(self, pressed_keys):
        pass

    def handle_hover_over(self, mouse_pos_as_vector: Vector2):
        pass

    def on_resize(self):
        pass

    def handle_left_mouse_down(self, pressed_keys):
        pass

    def __init__(self):
        GameTemplate.__init__(self,
                              input_state_handler=hkpa.InputStateHandler(
                                  key_actions=[
                                      hkpa.InputAction([hkpa.InputEvent(PyKeys.K_q,
                                                                        event_type=hkpa.InputEventType.DOWN)],
                                                       callback=lambda x: self._rotate_y_axis()),
                                      hkpa.InputAction([hkpa.InputEvent(PyKeys.K_a,
                                                                        event_type=hkpa.InputEventType.DOWN)],
                                                       callback=lambda x: self._rotate_x_axis())
                                  ]
                              ))
        self.particles = {}
        self.create_part_time = 0
        self.rotators = [] #np.array([10, 250, 67, 1])
        self.init_rotators()
        self.axis = np.array([1, 2, 0.5])
        self.rotation_vector = self.axis / (self.axis ** 2).sum() ** 0.5

        self.radians_per_sec = np.pi
        self.center = np.array([1000, 1000, 0])
        self.game_time = 0
        self.particle_size = 20

        self.index = -1



    def _rotate_x_axis(self):
        self.axis += np.array([.5, 0, 0])
        self.rotation_vector = self.axis / (self.axis ** 2).sum() ** 0.5


    def _rotate_y_axis(self):
        self.axis += np.array([0, 0.5, 0])
        self.rotation_vector = self.axis / (self.axis ** 2).sum() ** 0.5

    def _get_next_index(self):
        self.index += 1
        return self.index

    def init_rotators(self):
        self.rotators.append([np.array([10, 250, 67, 1]), Color.BLUE])
        self.rotators.append([np.array([250, 250, 10, 1]), Color.RED])
        self.rotators.append([np.array([750, 800, 10, 1]), Color.GREEN])


    def model_updater(self, delta_time_ms: int):
        rads = self.radians_per_sec * delta_time_ms / 1000
        matrix_other = rotateAroundAxis(self.center, self.rotation_vector, rads)

        if self.create_part_time > 100:
            self.create_part_time = 0
            for rotator in self.rotators:
                self.particles[Particle(self._get_next_index(), rotator[0], self.particle_size, 1,
                                        color=rotator[1])] = self.game_time

        for rotator in self.rotators:
            rotator[0] = np.dot(matrix_other, rotator[0])
            self.create_part_time += delta_time_ms
            self.game_time += delta_time_ms


        to_delete = []
        delete_time = 30000
        shrink_time = 3000

        for particle, create_time in self.particles.items():
            if self.game_time - create_time > delete_time:
                to_delete.append(particle)

            particle.size = int(max((1 - (self.game_time - create_time) / shrink_time) * self.particle_size, 1))

        for particle in to_delete:
            del self.particles[particle]

    def draw(self, frames:int, debug_mode:bool = False):
        for particle in self.particles.keys():
            particle.display(self.screen)

        # self.draw_fps(self.screen)

game = Game()
game.main()


rnd.seed(0)

axis = np.array([1, 0, 1])
rotation_vector = axis / (axis**2).sum()**0.5


for ii in range(0, 100):
    other = np.array([rnd.randint(0, 100), rnd.randint(0, 100), rnd.randint(0, 100)], dtype=float)
    center = np.array([rnd.randint(0, 100), rnd.randint(0, 100), rnd.randint(0, 100)], dtype=float)
    matrix_center = rotateAroundAxis(center, rotation_vector, .1)
    matrix_other = rotateAroundAxis(center, rotation_vector, np.pi * 2)

    translated_center = matrix_center.dot(np.append(center, 1))
    translated_other = matrix_other.dot(np.append(other, 1))
    # verify = translated_point[:2] == center
    if not np.allclose(translated_center[:3], center):
        print (translated_center[:3], center)
        raise Exception(f"Translated center does not equal center")

    if not np.allclose(translated_other[:3], other):
        print (matrix_other, translated_other[:3], other)
        raise Exception(f"Translated other does not equal other")
