module Main where

import Graphics.Gloss.Interface.Pure.Game
import qualified Data.Set as Set
import qualified Data.Map as Map
import CanvasData
import Croissant (parseConfigFile,getInt)
import Tea
import Data.Char (toLower)
import Data.List (intercalate)
import Data.Foldable (toList)
import Control.Monad (mapM_)
import Parser(runParser)
import Random
import Sequencing
import DataParsers
import Commander
import WindowSize (getWindowSize)

fps = 20

main = do
    colors   <- parseColors
    places   <- parsePlaces
    sizes    <- parseSizes
    times    <- parseTimes
    commands <- parseCommands
    (screenX,screenY) <- getWindowSize
    let info = Info (mkStdGen 100) [] colors shapes times sizes places commands (fromIntegral screenX, fromIntegral screenY) in
        play (FullScreen (screenX,screenY))
            white
            fps
            (startWorld screenX screenY info)
            toPicture
            handleInput
            stepWorld
            

startWorld :: Int -> Int -> Info -> World
startWorld w h i = World w h [] Set.empty True (0-fromIntegral w/2) (0-fromIntegral h/2) [] 0 i []

toPicture :: World -> Picture
toPicture w = pictures 
    [ pictures . map (\e -> translate (_posX e - xc) (_posY e - yc) $ _picture e) . _entities $ w
    , translate (_inputX w + 25) (_inputY w + 25) . scale 0.25 0.25 $ (Text $ _inputStr w ++ "_")
    ]
    where
    xc = (fromIntegral $ _screenX w) / 2
    yc = (fromIntegral $ _screenY w) / 2

handleInput :: Event -> World -> World
-- Delete characters when delete key is pressed.
handleInput (EventKey (SpecialKey KeyDelete) Down _ _) w = let str = _inputStr w in
    if not (null str) && _doDelete w then
        w {_doDelete = False, _inputStr = init $ _inputStr w}
    else
        w
handleInput (EventKey (SpecialKey KeyDelete) Up _ _) w = w {_doDelete = True}
-- Insert spaces when Spacebar is pressed.
handleInput (EventKey (SpecialKey KeySpace) Down _ _) w = 
    if Set.member ' ' (_keyDown w) then
        w
    else
        w {_keyDown = Set.insert ' ' $ _keyDown w, _inputStr = _inputStr w ++ [' ']}
handleInput (EventKey (SpecialKey KeySpace) Up _ _) w = w {_keyDown = Set.delete ' ' $ _keyDown w}
-- Add key to list of keys currently pressed.
handleInput (EventKey (Char char) Down _ _) w =
    if Set.member char (_keyDown w) then
        w
    else
        w {_keyDown = Set.insert char $ _keyDown w, _inputStr = _inputStr w ++ [char]}
handleInput (EventKey (Char char) Up _ _)           w = w {_keyDown = Set.delete char $ _keyDown w}
-- Enter Key Pressed. Execute command.
handleInput (EventKey (SpecialKey KeyEnter) Down _ _) w = case runParser draw $ (_info w){_words=combos $ _inputStr w} of
    (i,Nothing) -> w{_inputStr="",_info=i}
    (i,Just ok) -> w{_inputStr="",_info=i,_commands=_commands w ++ [ok]} 
handleInput _ w = w

stepWorld :: Float -> World -> World
stepWorld td w = case _commands w of
    []     -> w
    (x:xs) -> case x of
        DrawCommand t f -> 
            if t - td <= 0 then
                f w{_commands = xs}
            else
                w{_commands = DrawCommand (t-td) f : xs}