import pygame
import pygame_menu
import random as rand
from copy import deepcopy
import modules.User

pygame.init()
MAINSCREEN_SIZE = (1024,768)
MAINSCREEN = pygame.display.set_mode(MAINSCREEN_SIZE)
pygame.display.set_caption("Testgame")

WEISS   = ( 255, 255, 255)
SCHWARZ = (0,0,0)

active = True

clock = pygame.time.Clock()

#TODO: Make Grid for running Rect

class GameObject():
    __color = (0,0,0)
    __size_rect_x:int
    __size_rect_y:int
    __movespeed = int()
    __rectobjekt:pygame.Rect
    __surface = MAINSCREEN
    __hide = False
    __collided = False
    __is_player = False
    __is_rect = False
    __has_follower = False
    count = 0

    __movedirection = {"up":False, "down":False, "left":False, "right":False}
    
    def __init__(self, name:str, posx_init:int=0, posy_init:int=0, move_speed:int=0, is_player:bool = False, is_rect:bool = True, rect_size:tuple = (10,10)) -> None:
        self.__name = name
        self.__pos_x = posx_init
        self.__pos_y = posy_init
        self.pos_array = (posx_init,posy_init)
        self.__inital_pos_x = posx_init
        self.__initial_pos_y = posx_init
        self.__movespeed = move_speed
        self.__is_player = is_player
        self.__is_rect = is_rect
        self.__size_rect_x = rect_size[0]
        self.__size_rect_y = rect_size[1]
        self.count += 1
        self.__pos_lf_x = 0
        self.__pos_lf_y = 0

        #self.__rectobjekt = rect

    def change_direction(self, direction:dict):
        if(direction):
            for key in self.__movedirection.keys():
                self.__movedirection[key] = False
            self.__movedirection[direction] = True
            print(direction)
        pass

    def move(self, *speed:int):
        MOVE_SPEED = 1
        #self.__rectobjekt.x += MOVE_SPEED

        if(self.__movedirection['up']):
            if(not speed): self.__pos_y -= MOVE_SPEED
            else: self.__pos_y -= speed[0]
            if(self.__pos_y <= -self.__size_rect_y): 
                self.__pos_y = MAINSCREEN_SIZE[1]

        elif(self.__movedirection['down']):
            if(not speed): self.__pos_y += MOVE_SPEED
            else: self.__pos_y += speed[0]
            if(self.__pos_y >= MAINSCREEN_SIZE[1]): 
               self.__pos_y = -self.__size_rect_y           

        elif(self.__movedirection['left']):
            if(not speed): self.__pos_x -= MOVE_SPEED
            else: self.__pos_x -= speed[0]
            if(self.__pos_x <= -self.__size_rect_x): 
                self.__pos_x = MAINSCREEN_SIZE[0]          

        elif(self.__movedirection['right']):
            if(not speed): self.__pos_x += MOVE_SPEED
            else: self.__pos_x += speed[0]
            if(self.__pos_x >= MAINSCREEN_SIZE[0]): 
                self.__pos_x = -self.__size_rect_x        


    def move_in_steps(self, *speed:int, steps=10):
        MOVE_SPEED = 1
        #self.__rectobjekt.x += MOVE_SPEED

        if(self.__movedirection['up']):
            if(not speed): self.__pos_y -= MOVE_SPEED
            else: self.__pos_y -= speed[0]
            if(self.__pos_y <= -self.__size_rect_y): 
                self.__pos_y = MAINSCREEN_SIZE[1]

        elif(self.__movedirection['down']):
            if(not speed): self.__pos_y += MOVE_SPEED
            else: self.__pos_y += speed[0]
            if(self.__pos_y >= MAINSCREEN_SIZE[1]): 
               self.__pos_y = -self.__size_rect_y           

        elif(self.__movedirection['left']):
            if(not speed): self.__pos_x -= MOVE_SPEED
            else: self.__pos_x -= speed[0]
            if(self.__pos_x <= -self.__size_rect_x): 
                self.__pos_x = MAINSCREEN_SIZE[0]          

        elif(self.__movedirection['right']):
            if(not speed): self.__pos_x += MOVE_SPEED
            else: self.__pos_x += speed[0]
            if(self.__pos_x >= MAINSCREEN_SIZE[0]): 
                self.__pos_x = -self.__size_rect_x       

        
        #print("Objekt-Koordinaten "+self.__name+"= X: "+str(self.__rectobjekt.x)+" Y: "+str(self.__rectobjekt.y), end="\r")
    
    def draw(self):
        #font = pygame.font.SysFont(None, 70)
        #text = font.render("TEST", True, (0,0,0) )
        if(not self.__hide):
            self.__rectobjekt = pygame.draw.rect(self.__surface, self.__color, [self.__pos_x, self.__pos_y,self.__size_rect_x,self.__size_rect_y])

    def get_name(self, debug=False):
        if(debug):
            print(self.__name)
        return self.__name

    def get_position(self, debug=False):
        if(debug):
            print((self.__pos_x, self.__pos_y))
        return (self.__pos_x, self.__pos_y)

    def get_rect(self):
        return self.__rectobjekt
    
    def get_rect_size(self):
        return (self.__size_rect_x, self.__size_rect_y)
    
    def get_movespeed(self):
        return self.__movespeed
    
    def get_playermovedirection(self):
        return self.__movedirection
    
    def has_follower(self):
        return self.__has_follower
    
    def set_follower(self):
        self.__has_follower = True
    
    def is_collided(self) -> bool:
        return self.__collided
    
    def set_collided(self):
        self.__collided = True

    def set_position(self, pos:tuple):
        self.__pos_x = pos[0]
        self.__pos_y = pos[1]
    
    def update_pos_lastframe(self,x,y,debug=False):
        if (debug):
            print("Letzte Position: " + str((x,y)))
        self.__pos_lf_x = x
        self.__pos_lf_y = y

    def collide(self, GameObject) -> bool:
        #print(GameObject)
        #print(GameObject.get_rect())
        """TODO: Hitbox with Objectsize"""
            
        if(pygame.rect.Rect.colliderect(self.__rectobjekt, GameObject.get_rect()) and not self.is_collided()):
            print("Kollision\n") #Funktioniert für das erste!
            self.set_collided()
            return True
            #self.hide() #Löscht das Objekt nach einem Zusammenstoß mit Playerobject
        return False
    
    def hide(self):
        if(self.__hide != True):
            print("Gameoject mit der ID " + self.__name + " gelöscht!")
            self.__hide = True
        """TODO: Delete obeject function"""

#Behandelt später die Hauptschleife und Klassenobjekte
class Game():
    __state = {"win":False, "lose":False, "paused":False}
    def __init__(self) -> None:
        pass
#Handles all collided objects an adds it as Playerfollower

class Follower(GameObject):
    def __init__(self, name: str, posx_init: int = 0, posy_init: int = 0, move_speed: int = 0, is_player: bool = False, is_rect: bool = True, rect_size: tuple = (10, 10)) -> None:
        super().__init__(name, posx_init, posy_init, move_speed, is_player, is_rect, rect_size)

    def set_position_player(self, pos:tuple, playermovedirection:list, debug=False):
        if(playermovedirection["up"]):
            super().set_position((pos[0],pos[1]+super().get_rect_size()[1]))
            print(pos)
        if(playermovedirection["down"]):
            super().set_position((pos[0],pos[1]-super().get_rect_size()[1]))
            print(pos)
        if(playermovedirection["left"]):
            super().set_position((pos[0]+super().get_rect_size()[0],pos[1]))  
            print(pos)         
        if(playermovedirection["right"]):
            super().set_position((pos[0]-super().get_rect_size()[0],pos[1]))  
            print(pos) 
    def test(self):
        print(super().get_position())

def start_game():
    menu.disable()
    return 0

def apply_name(input):
    print(input)
    if(len(input) <= 0):
        print("Kein Name eingegeben!")
    else:
        menu.disable()
    #TODO: Add function for save name
    pass

count_follower = 0

def append_follwer(x,y):
    print("x: "+str(x), "y: "+str(y))
    newfollower = Follower("Follower "+str(count_follower), is_rect=True, rect_size=(x,y))
    colided_objects.append(newfollower)

menu = pygame_menu.Menu("Snake v1.0", 400, 300,)
menu.add.text_input("Name: ", onreturn=(apply_name))
menu.add.button('Play', start_game)
menu.add.button('Quit', pygame_menu.events.EXIT)
menu.mainloop(MAINSCREEN)

def spawn_entities(x:int, list_of_objects:list):
    count = 0
    for y in range(x):
        rect_size = 60
        Entity = GameObject("Entitiy-"+str(count), rand.randint(1,MAINSCREEN_SIZE[0]), rand.randint(1,MAINSCREEN_SIZE[1]), rand.randint(1,15), is_rect=True, rect_size=(rect_size,rect_size))
        Entity.get_name(True)
        list_of_objects.append(Entity)
        count += 1

Player = GameObject("Player", 10, 10, 10, is_player=False, is_rect=True, rect_size=(50,50))

background = pygame.surface.Surface((640,480))


x = 3600   
invert = False
colided_objects = list()
spawned_entities = list()
spawn_entities(30, spawned_entities)
count_hidden_entities = 0
count_spawend_enities = len(spawned_entities)
print("Es wurden " + str(count_spawend_enities)+ " Objekte gespawnt")

#Fenster-Hauptschleife
while active == True:   
    MAINSCREEN.fill((255,255,255))
    for event in pygame.event.get():
        if (event.type == pygame.QUIT):
            print("Programm wird geschlossen!")
            print(spawned_entities, end="\n")
            active = False
        elif (event.type == pygame.KEYDOWN):
            if (event.key == pygame.K_UP):
                print("Keydown")
                Player.change_direction("up")
            elif (event.key == pygame.K_DOWN):
                print("Keydown")
                Player.change_direction("down")
            elif (event.key == pygame.K_RIGHT):
                print("Keydown")
                Player.change_direction("right")
            elif (event.key == pygame.K_LEFT):
                print("Keydown")
                Player.change_direction("left")

    Player.draw()
    Player.update_pos_lastframe(Player.get_position()[0], Player.get_position()[1], True)
    Player.move(5)
    print("Aktuelle Position: " + str(Player.get_position()))
    #print("Aktuell kollidierte Objekte: ", str(count_hidden_entities))
    #Spawns the Entities
    for y in spawned_entities:
        y:GameObject
        y.draw()
        if(y.is_collided() == True):
            #Der erste Follower folgt dem Spieler, alle übrigen folgen den vorherien Verfolgern
            y.hide()
            pass
        if(y.is_collided() == False):
            if(y.collide(Player)):
                count_hidden_entities += 1  
                xy = y.get_rect_size()
                append_follwer(xy[0], xy[1])
                count_follower += 1

    #Zeichnet alle Verfolgerobjekte, sofern sie vorliegend sind
    #TODO: Follower sollen ab dem zweiten Objekt dem vorangegangenen Objekt folgen und nicht dem player

    #if(colided_objects):
     #   colided_objects[0].set_position_player(Player.get_position(), Player.get_playermovedirection(), True)
    i=0

    if(colided_objects):
        pass

    #TODO:Berechne Position follower Objekte anhand Position aus letztem Frame

    for follower in colided_objects:
        follower:Follower
        if(i >= 0):
            #colided_objects[0].set_position_player(Player.get_position(), Player.get_playermovedirection(), True)
            pass
        if(i > 0 and i <= len(colided_objects)):
            #follower.set_position_player(colided_objects[i].get_position(), Player.get_playermovedirection(), True)
            pass
        follower.draw()
        i += 1
            
                   

    if(count_hidden_entities == count_spawend_enities):
        print("WIN!!!")
        menu.enable()
        menu.add.label("WIN", "win", 10)
        menu.mainloop(MAINSCREEN)
        break
                   
    if(x == 0):
        for y in spawned_entities:
            y.hide()
        pass
    x -= 1

    """Drawing Lines test
    pos = 0
    for x in range(20): 
        pos += 60
        pygame.draw.line(MAINSCREEN, (0,0,0), (pos,0),(pos,MAINSCREEN_SIZE[1]))"""

    #print("Objekt-Koordinaten= X: "+str(rect1.x)+" Y: "+str(rect1.y)+"", end="\r")
    
    #Displayflip sorgt dafür, dass das Fenster entsprechend der Tickrate aktualisiert wird
    #pygame.display.flip()

    pygame.display.flip()
    clock.tick(60)
pygame.quit()