module Gamgine.State.StateTree where
import qualified Data.List as L
import qualified Graphics.UI.GLFW as GLFW
import qualified Gamgine.State.State as S
import qualified Gamgine.State.InputInfo as II
import qualified Gamgine.State.MouseInfo as MI
import qualified Gamgine.State.KeyInfo as KI

-- | the tree of application states and how they entered and leaved
data StateTree a = Branch {
   state     :: S.State a,
   enterWhen :: StateTransition,
   leaveWhen :: StateTransition,
   adjacents :: [StateTree a]
   }

-- | at which event the next state should be entered
type EnterWhen = StateTransition

-- | at which event the current state should be leaved
type LeaveWhen = StateTransition

-- | when a state should be entered or leaved
data StateTransition = ByKey GLFW.Key II.InputState
                     | ByKeyWithMod GLFW.Key II.InputState II.Modifier
                     | ByMouse GLFW.MouseButton II.InputState
                     | ByMouseWithMod GLFW.MouseButton II.InputState II.Modifier
                     | NoTransition
                     deriving (Eq, Ord)

root :: S.State a -> [StateTree a] -> StateTree a
root s as = Branch s NoTransition NoTransition as


enterState :: II.MousePos -> a -> StateTree a -> Maybe (a, StateTree a)
enterState mp a st@(Branch s e l as) =
   case (S.enter s) mp a of
        Just (a', s') -> Just (a', Branch s' e l as)
        _             -> Nothing


leaveState :: a -> StateTree a -> (a, StateTree a)
leaveState a (Branch s e l as) =
   let (a', s') = S.leave s $ a in (a', Branch s' e l as)


handleKeyEvent :: KI.KeyInfo -> a -> StateTree a -> (a, StateTree a)
handleKeyEvent ki a (Branch s e l as) =
   let (a', s') = (S.keyEvent s) ki a in (a', Branch s' e l as)


handleMouseEvent :: MI.MouseInfo -> a -> StateTree a -> (a, StateTree a)
handleMouseEvent mi a (Branch s e l as) =
   let (a', s') = (S.mouseEvent s) mi a in (a', Branch s' e l as)