{-# LANGUAGE TemplateHaskell , DeriveDataTypeable #-}

module Types where

import Control.Applicative
import Control.Lens
import Data.Acid
import Data.Aeson
import Data.Aeson.TH
import Data.SafeCopy
import Data.Typeable
import qualified Data.IntMap as I
import qualified Data.Text.Lazy as T

tupleMap :: (a -> b) -> (a,a) -> (b,b)
tupleMap f = bimap f f

data Play = Rock | Paper | Scissors deriving (Eq,Show,Enum,Read)

data RoundResult = Win | Draw | Lose deriving (Eq,Show,Read)

invertRoundResult :: RoundResult -> RoundResult
invertRoundResult Win = Lose
invertRoundResult Lose = Win
invertRoundResult Draw = Draw

calculateRoundResult :: Play -> Play -> RoundResult
calculateRoundResult Rock Paper = Lose
calculateRoundResult Paper Scissors = Lose
calculateRoundResult Scissors Rock = Lose
calculateRoundResult x y
    | x == y = Draw
    | otherwise = invertRoundResult $ calculateRoundResult y x

data Player = Player {
      _name :: T.Text
    , _playerIdNum :: Int
    } deriving (Eq,Show,Typeable)

makeLenses ''Player

data Game = Game {
      _participants :: (Int,Int)
    , _plays :: (Maybe Play, Maybe Play)
    , _lastPlay :: (Maybe Play, Maybe Play)
    , _results :: [RoundResult]
    , _winThreshold :: Int
    , _winner :: Maybe Int
    } deriving (Eq,Show,Typeable)
makeLenses ''Game

data App = App {
      _players :: I.IntMap Player
    , _games :: I.IntMap Game
} deriving (Eq,Show,Typeable)
makeLenses ''App

deriveSafeCopy 0 'base ''Play
deriveSafeCopy 0 'base ''RoundResult
deriveSafeCopy 0 'base ''Game
deriveSafeCopy 0 'base ''Player
deriveSafeCopy 0 'base ''App

$(deriveJSON defaultOptions ''Play)
$(deriveJSON defaultOptions ''RoundResult)
$(deriveJSON defaultOptions {fieldLabelModifier = drop 1} ''Game)
$(deriveJSON defaultOptions {fieldLabelModifier = drop 1} ''Player)
$(deriveJSON defaultOptions {fieldLabelModifier = drop 1} ''App)
