import random
import time

import pygame.time
from pygame import Vector2

from pyreverb.reverb import ReverbObject, ReverbManager, SyncVar

TICK = 60
MAP_SIZE = (800, 800)

clock = pygame.time.Clock()

@ReverbManager.reverb_object_attribute
class Bullet(ReverbObject):
    def __init__(self, pos, dir, color, belonging_membership: int = None):
        print(pos, dir, color)
        self.pos = SyncVar(pos)
        self.dir = SyncVar(dir)
        self.color = SyncVar(color)
        self.speed = 2
        super().__init__(self.pos, self.dir, self.color, belonging_membership=belonging_membership)

    def on_init_from_client(self):
        if self.is_owner():
            self.compute_server(self.die_after_time, 2)
            self.compute_server(self.update)

    # SERVER SIDE
    def die_after_time(self, t):
        time.sleep(t)
        ReverbManager.remove_reverb_object(self.uid)

    def update(self):
        while self.is_alive:
            self.pos.set(list(self.pos.get() + Vector2(self.dir.get()) * self.speed))
            clock.tick(TICK)


@ReverbManager.reverb_object_attribute
class Player(ReverbObject):
    def __init__(self, pos=[0, 0], dir=[0, 0], color="red", belonging_membership: int = None):
        self.pos = SyncVar(pos)
        self.dir = SyncVar(dir)
        self.color = SyncVar(color)
        super().__init__(self.pos, self.dir, self.color, belonging_membership=belonging_membership)

    def on_init_from_client(self):
        while self.is_alive:
            if self.is_owner():
                keys = pygame.key.get_pressed()
                dir = ""
                if keys[pygame.K_z]:
                    dir += "Z"
                if keys[pygame.K_s]:
                    dir += "S"
                if keys[pygame.K_q]:
                    dir += "Q"
                if keys[pygame.K_d]:
                    dir += "D"

                if dir != "":
                    self.compute_server(self.check_walk, dir)

                if keys[pygame.K_SPACE]:
                    self.compute_server(self.spawn_bullet)
                    time.sleep(1)

                clock.tick(TICK)

    @staticmethod
    def choose_rnd_color():
        return ["green", "red", "blue", "yellow"][random.randint(0, 3)]

    # ON SERVER
    def check_walk(self, dir):
        self.dir.set([0, 0])
        speed = 5

        def is_pos_in_map_bound(pos: Vector2):
            return 0 <= pos.x <= MAP_SIZE[0] and 0 <= pos.y <= MAP_SIZE[1]

        for d in dir:
            l_pos = {"Z": (0, -1), "S": (0, 1), "D": (1, 0), "Q": (-1, 0)}
            self.dir.set(tuple(self.dir.get() + Vector2(l_pos[d])))

        new_pos = self.pos.get() + Vector2(self.dir.get()) * speed
        if is_pos_in_map_bound(new_pos):
            self.pos.set(tuple(new_pos))

    def spawn_bullet(self):
        ReverbManager.add_new_reverb_object(
            Bullet(self.pos.get(), self.dir.get(), self.color.get(), belonging_membership=self.belonging_membership))
