import pygame
import random as rand


class GameObject():
    """TODO Install a body array with positions of mainbody and adders"""

    _size_rect_x:int
    _size_rect_y:int
    __movespeed = int()
    _rectobjekt:pygame.Rect
    _surface:pygame.Surface
    _mainscreensize:tuple
    __hide = False
    __collided = False
    __is_player = False
    __is_rect = False
    __has_follower = False
    __score:int
    count = 0
    
    def __init__(self, name:str, surface, mainscreensize:tuple, posx_init:int=0, posy_init:int=0, move_speed:int=0, is_player:bool = False, is_rect:bool = True, color:tuple = (0,0,0), rect_size:tuple = (10,10), image = str()) -> 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._surface = surface
        self._mainscreensize = mainscreensize
        self.__score = 0
        self.__imagepath = image
        self.__imageloaded = 0
        self.__color = color
    
    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 get_player_score(self) -> int:
        return self.__score
    
    def get_surface(self) -> pygame.Surface:
        return self._surface
    
    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 update_player_score(self, score_from_entity):
        if(score_from_entity > 0):
            self.__score += score_from_entity
        
    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"""

class GameObject_new():
    def __init__(self, name:str, surface:pygame.surface.Surface, surface_size:tuple, init_pos_x, init_pos_y, visibility:bool = True) -> None:
        self._name = name
        self._surface = surface
        self._surface_size = surface_size
        self._position = [init_pos_x, init_pos_y]
        self._visibility = visibility

    def printall_attributes(self):
        print(self._name)
        print(self._surface)
        print(self._surface_size)
        print(self._position)
        print(self._visibility)

    def get_position(self) -> tuple:
        return self._position



class Block(GameObject):
    __score = int()
    def __init__(self, name: str, surface, mainscreensize: tuple, posx_init: int = 0, posy_init: int = 0, move_speed: int = 0, is_player: bool = False, is_rect: bool = True, color: tuple = (0, 0, 0), rect_size: tuple = (10, 10), image=str()) -> None:
        super().__init__(name, surface, mainscreensize, posx_init, posy_init, move_speed, is_player, is_rect, color, rect_size, image)
        self.__score = rand.randint(5, 50)

    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 get_score(self) -> int:
        return self.__score
    
class Player(GameObject_new):
    #Later handles the Player-Gameobject
    def __init__(self, name: str, surface: pygame.Surface, surface_size: tuple, init_pos_x, init_pos_y, visibility: bool = True,
                 size:int = 10
                 ) -> None:
        self._size = size
        self._score = 0
        self._rect:pygame.Rect
        self.__snake_body = [[100,100+size], [100,100+size*2], [100,100+size*3], [100,size*5]]
        super().__init__(name, surface, surface_size, init_pos_x, init_pos_y, visibility)
        self.__snake = {"head":"data/models/snake_head_1.png", "body":"data/models/snake_body_1.png", "tail":""}
        self._startmoving = False

    __movedirection = {"up":False, "down":False, "left":False, "right":False}
    
    __test_counter = 0
    __player_rect:pygame.Rect
    

    def user_test_func(self):
        pass

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

    def move(self, *speed:int):
        MOVE_SPEED = 1
        if(self.__test_counter == 10):
            self.__test_counter = 0
            if(self.__movedirection['up']):
                if(not speed): self._position[1] -= MOVE_SPEED
                else: self._position[1] -= speed[0]
                if(self._position[1] <= -self._size): 
                    self._position[1] = self._surface_size[1]

            elif(self.__movedirection['down']):
                if(not speed): self._position[1] += MOVE_SPEED
                else: self._position[1] += speed[0]
                if(self._position[1] >= self._surface_size[1]): 
                    self._position[1] = -self._size            

            elif(self.__movedirection['left']):
                if(not speed): self._position[0] -= MOVE_SPEED
                else: self._position[0] -= speed[0]         
                if(self._position[0] <= -self._size): 
                    self._position[0] = self._surface_size[0] 

            elif(self.__movedirection['right']):
                if(not speed): self._position[0] += MOVE_SPEED
                else: self._position[0] += speed[0]
                if(self._position[0] >= self._surface_size[0]): 
                    self._position[0] = -self._size  
        self.__test_counter+=1

    def draw(self):
        if(self.__test_counter == 10):
            self.__snake_body.insert(0, list(self._position))
        counter = 0
        for pos in self.__snake_body:
            if(counter == 0): #Only for the first part of the Snkae, this meens the head
                #self.__player_rect = pygame.draw.rect(self._surface, (0,0,0), pygame.Rect(pos[0], pos[1], self._size, self._size))
                surface = pygame.Surface((40,120))
                surface.fill((255,255,255))
                image = pygame.image.load(self.__snake["head"])
                image = pygame.transform.scale(image, (40, 60))
                if(self.__movedirection["right"]): 
                    image = pygame.transform.rotate(image, 270) #Rotates the Snakehead on directionchange
                    surface = pygame.transform.rotate(surface, 270)
                if(self.__movedirection["left"]): 
                    image = pygame.transform.rotate(image, 90)
                    surface = pygame.transform.rotate(surface, 90)
                if(self.__movedirection["up"]): 
                    image = pygame.transform.rotate(image, 0)
                    surface = pygame.transform.rotate(surface, 0)
                if(self.__movedirection["down"]): 
                    image = pygame.transform.rotate(image, 180)
                    surface = pygame.transform.rotate(surface, 180)
                surface.blit(image, (0,0))
                self.__player_rect = self._surface.blit(surface, (pos[0], pos[1]))
            else:
                #pygame.draw.rect(self._surface, (0,0,0), pygame.Rect(pos[0], pos[1], self._size, self._size))
                surface = pygame.Surface((40,40))
                surface.fill((255,255,255))                
                image = pygame.image.load(self.__snake["body"])
                image = pygame.transform.scale(image, (30,40))
                image = pygame.transform.rotate(image, 270)


                surface.blit(image, (0,5))
                self._surface.blit(surface, (pos[0], pos[1]))
                #print((pos[0], pos[1]))
            counter += 1 
            #TODO Insert elif for the last position of the array, this meens the tail
        counter = 0
            #print(pos) 
        if(self.__test_counter == 10):    
            self.__snake_body.pop()

    def collide_fruit(self, rect:pygame.Rect):
        if(pygame.Rect.colliderect(self.get_player_rect(), rect)):
            return True
        else:
            return False
        
    def collide_self(self):
        count = len(self.__snake_body)
        for elements in range(1, count):
            if(self.get_position() == self.__snake_body[elements]):
                print(F"Colidepositions Player: {self.get_position()}  Object{self.__snake_body[elements]}") #For DEBUG only
                return True
        return False
    
    def add_body(self):
        self.__snake_body.append(list(self._position))
    
    def get_position(self) -> tuple:
        return self.__snake_body[0]

    def get_player_score(self) -> int:
        return self._score
    
    def get_positions_snake_body(self) -> list:
        return self.__snake_body
    
    def get_player_rect(self):
        return self.__player_rect
    
    def get_playermovedirection(self):
        return self.__movedirection
    
    def inc_score(self, points:int):
        self._score += points
    

class Fruit(GameObject_new):
    def __init__(self, name: str, surface: pygame.Surface, surface_size: tuple, init_pos_x, init_pos_y, visibility: bool = True, rect_size:int = 10, color:tuple = (0,0,0), score_points = 0, sprite=str()) -> None:
        super().__init__(name, surface, surface_size, init_pos_x, init_pos_y, visibility)

        self.__score_points = score_points
        self.__rect:pygame.Rect
        self.__rect_size = rect_size
        self.__color = color
        self.__image = pygame.image.load(sprite)

    def draw(self):
        #self.__rect = pygame.draw.rect(self._surface, self.__color, (self._position[0], self._position[1], self.__rect_size, self.__rect_size))
        self.__rect = self._surface.blit(self.__image, self.get_position())
        
    def get_rect(self) -> pygame.Rect:
        return self.__rect
    
    def get_score_points(self) -> int:
        return self.__score_points

    


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

        self.__image = pygame.image.load(image).convert()
        #self.__image = pygame.transform.scale(self.__image, (20, 20))  Scale the selected image

    def move(self):
        pass

    def draw(self):
        surface = self.get_surface()
        surface.blit(self.__image, self.get_position())