{-# LANGUAGE DeriveGeneric #-}
-- | Abstract syntax of human player commands.
module Game.LambdaHack.Client.UI.HumanCmd
  ( CmdCategory(..), categoryDescription
  , CmdArea(..), areaDescription
  , CmdTriple, AimModeCmd(..), HumanCmd(..)
  , TriggerItem(..)
  ) where

import Prelude ()

import Game.LambdaHack.Core.Prelude

import           Control.DeepSeq
import           Data.Binary
import           GHC.Generics (Generic)
import qualified NLP.Miniutter.English as MU

import Game.LambdaHack.Common.Vector
import Game.LambdaHack.Content.ItemKind (ItemKind)
import Game.LambdaHack.Definition.Defs

data CmdCategory =
    CmdDashboard | CmdItemMenu
  | CmdMove | CmdItem | CmdAim | CmdMeta | CmdMouse
  | CmdInternal | CmdDebug | CmdMinimal
  deriving (Show, Read, Eq, Generic)

instance NFData CmdCategory

instance Binary CmdCategory

categoryDescription :: CmdCategory -> Text
categoryDescription CmdDashboard = "Dashboard"
categoryDescription CmdItemMenu = "Item menu commands"
categoryDescription CmdMove = "Terrain exploration and modification commands"
categoryDescription CmdItem = "All item-related commands"
categoryDescription CmdAim = "All aiming commands"
categoryDescription CmdMeta = "Assorted commands"
categoryDescription CmdMouse = "Mouse"
categoryDescription CmdInternal = "Internal"
categoryDescription CmdDebug = "Debug"
categoryDescription CmdMinimal = "The minimal command set"

-- The constructors are sorted, roughly, wrt inclusion, then top to bottom,
-- the left to right.
-- | Symbolic representation of areas of the screen used to define the meaning
-- of mouse button presses relative to where the mouse points to.
data CmdArea =
    CaMessage
  | CaMapLeader
  | CaMapParty
  | CaMap
  | CaLevelNumber
  | CaArenaName
  | CaPercentSeen
  | CaXhairDesc
  | CaSelected
  | CaCalmGauge
  | CaCalmValue
  | CaHPGauge
  | CaHPValue
  | CaLeaderDesc
  deriving (Show, Read, Eq, Ord, Generic)

instance NFData CmdArea

instance Binary CmdArea

areaDescription :: CmdArea -> Text
areaDescription ca = case ca of
  CaMessage ->      "message line"
  CaMapLeader ->    "pointman tile"
  CaMapParty ->     "party on map"
  CaMap ->          "the map area"
  CaLevelNumber ->  "level number"
  CaArenaName ->    "level caption"
  CaPercentSeen ->  "percent seen"
  CaXhairDesc ->    "crosshair info"
  CaSelected ->     "party roster"
  CaCalmGauge ->    "Calm gauge"
  CaCalmValue ->    "Calm value"
  CaHPGauge ->      "HP gauge"
  CaHPValue ->      "HP value"
  CaLeaderDesc ->   "pointman info"
  --                 1234567890123

-- | This triple of command categories, description and the command term itself
-- defines the meaning of a human command as entered via a keypress,
-- mouse click or chosen from a menu.
type CmdTriple = ([CmdCategory], Text, HumanCmd)

data AimModeCmd = AimModeCmd {exploration :: HumanCmd, aiming :: HumanCmd}
  deriving (Show, Read, Eq, Ord, Generic)

instance NFData AimModeCmd

instance Binary AimModeCmd

-- | Abstract syntax of human player commands.
data HumanCmd =
    -- Meta.
    Macro [String]
  | ByArea [(CmdArea, HumanCmd)]  -- if outside the areas, do nothing
  | ByAimMode AimModeCmd
  | ComposeIfLocal HumanCmd HumanCmd
  | ComposeUnlessError HumanCmd HumanCmd
  | Compose2ndLocal HumanCmd HumanCmd
  | LoopOnNothing HumanCmd
  | ExecuteIfClear HumanCmd
    -- Global.
    -- These usually take time.
  | Wait
  | Wait10
  | Yell
  | MoveDir Vector
  | RunDir Vector
  | RunOnceAhead
  | MoveOnceToXhair
  | RunOnceToXhair
  | ContinueToXhair
  | MoveItem [CStore] CStore (Maybe Text) Bool
  | Project
  | Apply
  | AlterDir
  | AlterWithPointer
  | CloseDir
  | Help
  | Hint
  | ItemMenu
  | MainMenu
  | MainMenuAutoOn
  | MainMenuAutoOff
  | Dashboard
    -- Below this line, commands do not take time.
  | GameDifficultyIncr Int
  | GameFishToggle
  | GameGoodsToggle
  | GameWolfToggle
  | GameKeeperToggle
  | GameScenarioIncr Int
  | GameRestart
  | GameQuit
  | GameDrop
  | GameExit
  | GameSave
  | Doctrine
  | Automate
  | AutomateToggle
  | AutomateBack
    -- Local. Below this line, commands do not notify the server.
  | ChooseItem ItemDialogMode
  | ChooseItemMenu ItemDialogMode
  | ChooseItemProject [TriggerItem]
  | ChooseItemApply [TriggerItem]
  | PickLeader Int
  | PickLeaderWithPointer
  | PointmanCycle Direction
  | PointmanCycleLevel Direction
  | SelectActor
  | SelectNone
  | SelectWithPointer
  | Repeat Int
  | RepeatLast Int
  | Record
  | AllHistory
  | MarkVision Int
  | MarkSmell
  | MarkSuspect Int
  | MarkAnim
  | OverrideTut Int
  | SettingsMenu
  | ChallengeMenu
  | PrintScreen
    -- These are mostly related to aiming.
  | Cancel
  | Accept
  | DetailCycle
  | ClearTargetIfItemClear
  | ItemClear
  | MoveXhair Vector Int
  | AimTgt
  | AimFloor
  | AimEnemy
  | AimItem
  | AimAscend Int
  | EpsIncr Direction
  | XhairUnknown
  | XhairItem
  | XhairStair Bool
  | XhairPointerFloor
  | XhairPointerMute
  | XhairPointerEnemy
  | AimPointerFloor
  | AimPointerEnemy
  deriving (Show, Read, Eq, Ord, Generic)

instance NFData HumanCmd

instance Binary HumanCmd

-- | Description of how item manipulation is triggered and communicated
-- to the player.
data TriggerItem =
  TriggerItem {tiverb :: MU.Part, tiobject :: MU.Part, tisymbols :: [ContentSymbol ItemKind]}
  deriving (Show, Eq, Ord, Generic)

instance Read TriggerItem where
  readsPrec = error $ "parsing of TriggerItem not implemented" `showFailure` ()

instance NFData TriggerItem

instance Binary TriggerItem
