content: module Game.HSnake.Player where
  
  import Control.Lens
  
  import Game.HSnake.Basic
  import Game.HSnake.Snake
  
  import Data.List
  
  data PlayerType = AI | Human
      deriving (Eq, Show)
  
  data Player = Player {
      _playerType         :: PlayerType
     ,_snake              :: Snake
       {-|
            Temporary state variable to store next move's snake direction
            Without this when snake went North, and user quickly typed
            West, then South, snake would bump into itself
       -}
     ,_nextSnakeDirection :: Direction
     ,_colour             :: Colour
  } deriving (Eq, Show)
  
  makeLenses ''Player
  
  initialPlayer :: Player
  initialPlayer = Player
                Human
                initialSnake
                (initialSnake^.direction)
                Green
  
  initialPlayerBottom :: Player
  initialPlayerBottom = Player
                Human
                initialSnakeBottom
                (initialSnakeBottom^.direction)
                Green
  
  initialComputer :: Player
  initialComputer = Player
                AI
                initialSnakeBottom
                (initialSnakeBottom^.direction)
                Blue
  
  isHuman :: Player -> Bool
  isHuman (Player Human _ _ _) = True
  isHuman _ = False
  
  checkPlayerCollision :: Player -> Bool
  checkPlayerCollision player = checkCollision $ player^.snake
  
  movePlayer :: Player -> Player
  movePlayer pl = snake .~ (moveSnake $ pl^.snake) $ pl
  
  playerEatsApple :: Point -> Player -> Bool
  playerEatsApple apple player = snakeEatsApple (player^.snake) apple
  
  sumPlayersPosition :: [Player] -> [Point]
  sumPlayersPosition ps = foldl (++) [] $ map (\pl -> pl^.snake^.position) ps
  
  totalPlayersPosition :: [Player] -> [Point]
  totalPlayersPosition = nub . sumPlayersPosition
  
  checkPlayersCollision :: [Player] -> Bool
  checkPlayersCollision ps = (length (filter checkPlayerCollision ps) > 0) ||
                            (length (totalPlayersPosition ps) < (length (sumPlayersPosition ps)))
  
  increasePlayerSnakeLength :: Player -> Player
  increasePlayerSnakeLength pl = snake .~ (increaseSnakeLength $ pl^.snake) $ pl
  
  setNextPlayerDirection :: Player -> Direction -> Player
  setNextPlayerDirection pl dir = nextSnakeDirection .~ dir $ pl
  
  updatePlayerDirection :: Player -> Player
  updatePlayerDirection pl = snake .~ changeSnakeDirection (pl^.snake) (pl^.nextSnakeDirection) $ pl
  