{-# LANGUAGE DeriveGeneric #-}

module PetrusFiles
  where

import Control.Monad
import Data.Maybe 
import Data.Aeson
import GHC.Generics
import Text.Read
import qualified Data.ByteString.Lazy as BS

data BuildingNodeType = Corridor|Office|Elevator|Entrance deriving (Show,Eq)

data BuildingNode = BuildingNode {
  id :: Int,
  x :: Int,
  y :: Int,
  floor :: Int,
  ntype :: BuildingNodeType
  } deriving(Show)


parseBNT :: String -> Maybe BuildingNodeType
parseBNT "CORRIDOR" = Just Corridor
parseBNT "OFFICE" = Just Office
parseBNT "ELEVATOR" = Just Elevator
parseBNT "ENTRANCE" = Just Entrance
parseBNT _ = Nothing

split :: (Eq a) => a -> [a] -> [[a]]
split _ [] = [[]]
split sep (x:xs) 
  | sep == x = [] : (split sep xs)
  | otherwise = (x:last):rest
  where
    (last:rest) = split sep xs

parseNodeDataFile :: String -> [BuildingNode]
parseNodeDataFile = (mapMaybe parseLine) . lines
  where
    parseLine :: String -> Maybe BuildingNode
    parseLine = parseSplitLine . (split ',')
      where
        parseSplitLine :: [String] -> Maybe BuildingNode
        parseSplitLine [id,x,y,floor,ntype] =
          (liftM5 BuildingNode) (readMaybe id) (readMaybe x) (readMaybe y) (readMaybe floor) (parseBNT ntype)
        parseSplitLine _ = Nothing


data Edge = Edge {
  from :: Int,
  to :: Int
  } deriving (Show,Generic, Eq)
  

data GameGraph = GameGraph {
  vertexCount :: Int,
  edges :: [Edge]
  } deriving (Show,Generic)

data StaticGameConfiguration = StaticGameConfiguration {
  graph :: GameGraph,
  targets :: [Int],
  spawns :: [Int],
  defenderPenalties :: [[Int]],
  attackerRewards :: [[Int]],
  vertexDefenderRewards :: [[Int]],
  vertexAttackerPenalties :: [[Int]],
  defenderCount :: Int,
  defenseProbabilityFunc :: String,
  stateHistoryHorizon :: Int,
  historyTimeHorizon :: Int
  } deriving (Show,Generic)

data SimpleGameConfiguration = SimpleGameConfiguration {
  staticGameConfiguration :: StaticGameConfiguration,
  attackerCount :: Int
  } deriving (Show,Generic)

instance FromJSON Edge
instance FromJSON GameGraph
instance FromJSON StaticGameConfiguration
instance FromJSON SimpleGameConfiguration

parseGameFile :: BS.ByteString -> Either String SimpleGameConfiguration
parseGameFile = eitherDecode

