{- |
Copyright: (c) 2017-2019 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>

Decision data type.
-}

module Summoner.Decision
       ( Decision (..)
       , decisionToBool
       , decisionsToBools
       , promptDecisionToBool
       ) where

import Summoner.Question (YesNoPrompt (..), chooseYesNoBool, falseMessage, trueMessage)


-- | Used for detecting the user decision during CLI input.
data Decision
    = Idk
    | Nop
    | Yes
    deriving stock (Int -> Decision -> ShowS
[Decision] -> ShowS
Decision -> String
(Int -> Decision -> ShowS)
-> (Decision -> String) -> ([Decision] -> ShowS) -> Show Decision
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Decision] -> ShowS
$cshowList :: [Decision] -> ShowS
show :: Decision -> String
$cshow :: Decision -> String
showsPrec :: Int -> Decision -> ShowS
$cshowsPrec :: Int -> Decision -> ShowS
Show, Decision -> Decision -> Bool
(Decision -> Decision -> Bool)
-> (Decision -> Decision -> Bool) -> Eq Decision
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Decision -> Decision -> Bool
$c/= :: Decision -> Decision -> Bool
== :: Decision -> Decision -> Bool
$c== :: Decision -> Decision -> Bool
Eq, Int -> Decision
Decision -> Int
Decision -> [Decision]
Decision -> Decision
Decision -> Decision -> [Decision]
Decision -> Decision -> Decision -> [Decision]
(Decision -> Decision)
-> (Decision -> Decision)
-> (Int -> Decision)
-> (Decision -> Int)
-> (Decision -> [Decision])
-> (Decision -> Decision -> [Decision])
-> (Decision -> Decision -> [Decision])
-> (Decision -> Decision -> Decision -> [Decision])
-> Enum Decision
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Decision -> Decision -> Decision -> [Decision]
$cenumFromThenTo :: Decision -> Decision -> Decision -> [Decision]
enumFromTo :: Decision -> Decision -> [Decision]
$cenumFromTo :: Decision -> Decision -> [Decision]
enumFromThen :: Decision -> Decision -> [Decision]
$cenumFromThen :: Decision -> Decision -> [Decision]
enumFrom :: Decision -> [Decision]
$cenumFrom :: Decision -> [Decision]
fromEnum :: Decision -> Int
$cfromEnum :: Decision -> Int
toEnum :: Int -> Decision
$ctoEnum :: Int -> Decision
pred :: Decision -> Decision
$cpred :: Decision -> Decision
succ :: Decision -> Decision
$csucc :: Decision -> Decision
Enum, Decision
Decision -> Decision -> Bounded Decision
forall a. a -> a -> Bounded a
maxBound :: Decision
$cmaxBound :: Decision
minBound :: Decision
$cminBound :: Decision
Bounded, (forall x. Decision -> Rep Decision x)
-> (forall x. Rep Decision x -> Decision) -> Generic Decision
forall x. Rep Decision x -> Decision
forall x. Decision -> Rep Decision x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Decision x -> Decision
$cfrom :: forall x. Decision -> Rep Decision x
Generic)

instance Semigroup Decision where
    (<>) :: Decision -> Decision -> Decision
    Idk <> :: Decision -> Decision -> Decision
<> x :: Decision
x   = Decision
x
    x :: Decision
x   <> Idk = Decision
x
    _   <> x :: Decision
x   = Decision
x

instance Monoid Decision where
    mempty :: Decision
mempty  = Decision
Idk
    mappend :: Decision -> Decision -> Decision
mappend = Decision -> Decision -> Decision
forall a. Semigroup a => a -> a -> a
(<>)

-- | Translate 'Decision' to 'Bool'.
decisionToBool :: Decision -> Bool
decisionToBool :: Decision -> Bool
decisionToBool = \case
    Yes -> Bool
True
    Nop -> Bool
False
    Idk -> Bool
False

-- | Prompt the 'Decision' to terminal output depending on the value.
promptDecisionToBool :: Decision -> YesNoPrompt -> IO Bool
promptDecisionToBool :: Decision -> YesNoPrompt -> IO Bool
promptDecisionToBool decision :: Decision
decision target :: YesNoPrompt
target@YesNoPrompt {..} = case Decision
decision of
    Yes -> Text -> IO Bool
trueMessage  Text
yesNoTarget
    Nop -> Text -> IO Bool
falseMessage Text
yesNoTarget
    Idk -> YesNoPrompt -> IO Bool
chooseYesNoBool YesNoPrompt
target

-- | Translate a pair of dependant 'Decision's to the pair of 'Bool's.
decisionsToBools :: (Decision, Decision) -> (Bool, Bool)
decisionsToBools :: (Decision, Decision) -> (Bool, Bool)
decisionsToBools = \case
    (Idk, Idk) -> (Bool
True, Bool
True)
    (Yes, Idk) -> (Bool
True, Bool
False)
    (Idk, Yes) -> (Bool
False, Bool
True)
    (Nop, Idk) -> (Bool
False, Bool
True)
    (Idk, Nop) -> (Bool
True, Bool
False)
    (x :: Decision
x, y :: Decision
y)     -> (Decision -> Bool
decisionToBool Decision
x, Decision -> Bool
decisionToBool Decision
y)