{-# LANGUAGE NoPolyKinds #-}

-- | Commands and stuff
module CalamityCommands.Command (Command (..)) where

import CalamityCommands.Check
import CalamityCommands.Error
import CalamityCommands.Group
import CalamityCommands.ParameterInfo

import Control.Lens hiding (Context, (<.>))

import Data.Kind (Type)
import Data.List.NonEmpty (NonEmpty)
import Data.Text as T

import GHC.Generics

import qualified Data.List.NonEmpty as NE
import TextShow
import qualified TextShow.Generic as TSG

-- | A command, paremeterised over its context
data Command (m :: Type -> Type) (c :: Type) (a :: Type) = forall p.
  Command
  { Command m c a -> NonEmpty Text
names :: NonEmpty T.Text
  , Command m c a -> Maybe (Group m c a)
parent :: Maybe (Group m c a)
  , -- | If this command is hidden
    Command m c a -> Bool
hidden :: Bool
  , -- | A list of checks that must pass for this command to be invoked
    Command m c a -> [Check m c]
checks :: [Check m c]
  , -- | A list of parameter metadata
    Command m c a -> [ParameterInfo]
params :: [ParameterInfo]
  , -- | A function producing the \'help\' for the command.
    Command m c a -> c -> Text
help :: c -> T.Text
  , -- | A function that parses the context for the command, producing the input
    -- @a@ for the command.
    ()
parser :: c -> m (Either CommandError p)
  , -- | A function that given the context and the input (@p@) of the command,
    -- performs the action of the command.
    ()
callback :: (c, p) -> m (Either T.Text a)
  }

data CommandS = CommandS
  { CommandS -> NonEmpty Text
names :: NonEmpty T.Text
  , CommandS -> [ParameterInfo]
params :: [ParameterInfo]
  , CommandS -> Maybe Text
parent :: Maybe T.Text
  , CommandS -> [Text]
checks :: [T.Text]
  , CommandS -> Bool
hidden :: Bool
  }
  deriving ((forall x. CommandS -> Rep CommandS x)
-> (forall x. Rep CommandS x -> CommandS) -> Generic CommandS
forall x. Rep CommandS x -> CommandS
forall x. CommandS -> Rep CommandS x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CommandS x -> CommandS
$cfrom :: forall x. CommandS -> Rep CommandS x
Generic, Int -> CommandS -> ShowS
[CommandS] -> ShowS
CommandS -> String
(Int -> CommandS -> ShowS)
-> (CommandS -> String) -> ([CommandS] -> ShowS) -> Show CommandS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CommandS] -> ShowS
$cshowList :: [CommandS] -> ShowS
show :: CommandS -> String
$cshow :: CommandS -> String
showsPrec :: Int -> CommandS -> ShowS
$cshowsPrec :: Int -> CommandS -> ShowS
Show)
  deriving (Int -> CommandS -> Builder
Int -> CommandS -> Text
Int -> CommandS -> Text
[CommandS] -> Builder
[CommandS] -> Text
[CommandS] -> Text
CommandS -> Builder
CommandS -> Text
CommandS -> Text
(Int -> CommandS -> Builder)
-> (CommandS -> Builder)
-> ([CommandS] -> Builder)
-> (Int -> CommandS -> Text)
-> (CommandS -> Text)
-> ([CommandS] -> Text)
-> (Int -> CommandS -> Text)
-> (CommandS -> Text)
-> ([CommandS] -> Text)
-> TextShow CommandS
forall a.
(Int -> a -> Builder)
-> (a -> Builder)
-> ([a] -> Builder)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> TextShow a
showtlList :: [CommandS] -> Text
$cshowtlList :: [CommandS] -> Text
showtl :: CommandS -> Text
$cshowtl :: CommandS -> Text
showtlPrec :: Int -> CommandS -> Text
$cshowtlPrec :: Int -> CommandS -> Text
showtList :: [CommandS] -> Text
$cshowtList :: [CommandS] -> Text
showt :: CommandS -> Text
$cshowt :: CommandS -> Text
showtPrec :: Int -> CommandS -> Text
$cshowtPrec :: Int -> CommandS -> Text
showbList :: [CommandS] -> Builder
$cshowbList :: [CommandS] -> Builder
showb :: CommandS -> Builder
$cshowb :: CommandS -> Builder
showbPrec :: Int -> CommandS -> Builder
$cshowbPrec :: Int -> CommandS -> Builder
TextShow) via TSG.FromGeneric CommandS

instance Show (Command m c a) where
  showsPrec :: Int -> Command m c a -> ShowS
showsPrec Int
d Command{NonEmpty Text
names :: NonEmpty Text
$sel:names:Command :: forall (m :: * -> *) c a. Command m c a -> NonEmpty Text
names, [ParameterInfo]
params :: [ParameterInfo]
$sel:params:Command :: forall (m :: * -> *) c a. Command m c a -> [ParameterInfo]
params, Maybe (Group m c a)
parent :: Maybe (Group m c a)
$sel:parent:Command :: forall (m :: * -> *) c a. Command m c a -> Maybe (Group m c a)
parent, [Check m c]
checks :: [Check m c]
$sel:checks:Command :: forall (m :: * -> *) c a. Command m c a -> [Check m c]
checks, Bool
hidden :: Bool
$sel:hidden:Command :: forall (m :: * -> *) c a. Command m c a -> Bool
hidden} =
    Int -> CommandS -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
d (CommandS -> ShowS) -> CommandS -> ShowS
forall a b. (a -> b) -> a -> b
$
      NonEmpty Text
-> [ParameterInfo] -> Maybe Text -> [Text] -> Bool -> CommandS
CommandS
        NonEmpty Text
names
        [ParameterInfo]
params
        (NonEmpty Text -> Text
forall a. NonEmpty a -> a
NE.head (NonEmpty Text -> Text) -> Maybe (NonEmpty Text) -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (Group m c a)
parent Maybe (Group m c a)
-> Getting
     (First (NonEmpty Text)) (Maybe (Group m c a)) (NonEmpty Text)
-> Maybe (NonEmpty Text)
forall s a. s -> Getting (First a) s a -> Maybe a
^? (Group m c a -> Const (First (NonEmpty Text)) (Group m c a))
-> Maybe (Group m c a)
-> Const (First (NonEmpty Text)) (Maybe (Group m c a))
forall a b. Prism (Maybe a) (Maybe b) a b
_Just ((Group m c a -> Const (First (NonEmpty Text)) (Group m c a))
 -> Maybe (Group m c a)
 -> Const (First (NonEmpty Text)) (Maybe (Group m c a)))
-> ((NonEmpty Text
     -> Const (First (NonEmpty Text)) (NonEmpty Text))
    -> Group m c a -> Const (First (NonEmpty Text)) (Group m c a))
-> Getting
     (First (NonEmpty Text)) (Maybe (Group m c a)) (NonEmpty Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsLabel
  "names"
  ((NonEmpty Text -> Const (First (NonEmpty Text)) (NonEmpty Text))
   -> Group m c a -> Const (First (NonEmpty Text)) (Group m c a))
(NonEmpty Text -> Const (First (NonEmpty Text)) (NonEmpty Text))
-> Group m c a -> Const (First (NonEmpty Text)) (Group m c a)
#names)
        ([Check m c]
checks [Check m c] -> Getting (Endo [Text]) [Check m c] Text -> [Text]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Check m c -> Const (Endo [Text]) (Check m c))
-> [Check m c] -> Const (Endo [Text]) [Check m c]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Check m c -> Const (Endo [Text]) (Check m c))
 -> [Check m c] -> Const (Endo [Text]) [Check m c])
-> ((Text -> Const (Endo [Text]) Text)
    -> Check m c -> Const (Endo [Text]) (Check m c))
-> Getting (Endo [Text]) [Check m c] Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsLabel
  "name"
  ((Text -> Const (Endo [Text]) Text)
   -> Check m c -> Const (Endo [Text]) (Check m c))
(Text -> Const (Endo [Text]) Text)
-> Check m c -> Const (Endo [Text]) (Check m c)
#name)
        Bool
hidden

instance TextShow (Command m c a) where
  showbPrec :: Int -> Command m c a -> Builder
showbPrec Int
d Command{NonEmpty Text
names :: NonEmpty Text
$sel:names:Command :: forall (m :: * -> *) c a. Command m c a -> NonEmpty Text
names, [ParameterInfo]
params :: [ParameterInfo]
$sel:params:Command :: forall (m :: * -> *) c a. Command m c a -> [ParameterInfo]
params, Maybe (Group m c a)
parent :: Maybe (Group m c a)
$sel:parent:Command :: forall (m :: * -> *) c a. Command m c a -> Maybe (Group m c a)
parent, [Check m c]
checks :: [Check m c]
$sel:checks:Command :: forall (m :: * -> *) c a. Command m c a -> [Check m c]
checks, Bool
hidden :: Bool
$sel:hidden:Command :: forall (m :: * -> *) c a. Command m c a -> Bool
hidden} =
    Int -> CommandS -> Builder
forall a. TextShow a => Int -> a -> Builder
showbPrec Int
d (CommandS -> Builder) -> CommandS -> Builder
forall a b. (a -> b) -> a -> b
$
      NonEmpty Text
-> [ParameterInfo] -> Maybe Text -> [Text] -> Bool -> CommandS
CommandS
        NonEmpty Text
names
        [ParameterInfo]
params
        (NonEmpty Text -> Text
forall a. NonEmpty a -> a
NE.head (NonEmpty Text -> Text) -> Maybe (NonEmpty Text) -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (Group m c a)
parent Maybe (Group m c a)
-> Getting
     (First (NonEmpty Text)) (Maybe (Group m c a)) (NonEmpty Text)
-> Maybe (NonEmpty Text)
forall s a. s -> Getting (First a) s a -> Maybe a
^? (Group m c a -> Const (First (NonEmpty Text)) (Group m c a))
-> Maybe (Group m c a)
-> Const (First (NonEmpty Text)) (Maybe (Group m c a))
forall a b. Prism (Maybe a) (Maybe b) a b
_Just ((Group m c a -> Const (First (NonEmpty Text)) (Group m c a))
 -> Maybe (Group m c a)
 -> Const (First (NonEmpty Text)) (Maybe (Group m c a)))
-> ((NonEmpty Text
     -> Const (First (NonEmpty Text)) (NonEmpty Text))
    -> Group m c a -> Const (First (NonEmpty Text)) (Group m c a))
-> Getting
     (First (NonEmpty Text)) (Maybe (Group m c a)) (NonEmpty Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsLabel
  "names"
  ((NonEmpty Text -> Const (First (NonEmpty Text)) (NonEmpty Text))
   -> Group m c a -> Const (First (NonEmpty Text)) (Group m c a))
(NonEmpty Text -> Const (First (NonEmpty Text)) (NonEmpty Text))
-> Group m c a -> Const (First (NonEmpty Text)) (Group m c a)
#names)
        ([Check m c]
checks [Check m c] -> Getting (Endo [Text]) [Check m c] Text -> [Text]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Check m c -> Const (Endo [Text]) (Check m c))
-> [Check m c] -> Const (Endo [Text]) [Check m c]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Check m c -> Const (Endo [Text]) (Check m c))
 -> [Check m c] -> Const (Endo [Text]) [Check m c])
-> ((Text -> Const (Endo [Text]) Text)
    -> Check m c -> Const (Endo [Text]) (Check m c))
-> Getting (Endo [Text]) [Check m c] Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsLabel
  "name"
  ((Text -> Const (Endo [Text]) Text)
   -> Check m c -> Const (Endo [Text]) (Check m c))
(Text -> Const (Endo [Text]) Text)
-> Check m c -> Const (Endo [Text]) (Check m c)
#name)
        Bool
hidden