module FortyTwo.Prompts.Confirm (confirm, confirmWithDefault) where

import Control.Monad.IO.Class
import qualified Data.Text as T

import FortyTwo.Renderers.Confirm (renderConfirm)
import FortyTwo.Renderers.Question (renderQuestion)
import FortyTwo.Utils (clearLines, flush)
import FortyTwo.Constants (emptyString)

-- | Normalize a string transforming it to lowercase and trimming it and getting either n or y
-- >>> normalizeString "Yes"
-- "y"
normalizeString :: String -> String
normalizeString :: String -> String
normalizeString String
s = forall a. Int -> [a] -> [a]
take Int
1 forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack forall a b. (a -> b) -> a -> b
$ Text -> Text
T.strip forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
T.toLower forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
s

-- | Get a clean user input string
getCleanConfirm :: MonadIO m => m String
getCleanConfirm :: forall (m :: * -> *). MonadIO m => m String
getCleanConfirm = do String
s <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO String
getLine; forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ String -> String
normalizeString String
s

-- | Ask a confirm falling back to a default value if no answer will be provided
confirmWithDefault :: MonadIO m => String -> Bool -> m Bool
confirmWithDefault :: forall (m :: * -> *). MonadIO m => String -> Bool -> m Bool
confirmWithDefault String
question Bool
defaultAnswer = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
  String -> IO ()
putStrLn String
emptyString
  forall (m :: * -> *).
MonadIO m =>
String -> String -> String -> m ()
renderQuestion String
question String
defaultAnswerHumanized String
emptyString
  forall (m :: * -> *). MonadIO m => Bool -> m ()
renderConfirm Bool
defaultAnswer
  IO ()
flush
  String
answer <- forall (m :: * -> *). MonadIO m => m String
getCleanConfirm
  forall (m :: * -> *). MonadIO m => Int -> m ()
clearLines Int
1
  if String
answer forall a. Eq a => a -> a -> Bool
== String
"n" Bool -> Bool -> Bool
|| (String
answer forall a. Eq a => a -> a -> Bool
/= String
"y" Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
defaultAnswer) then do
    forall (m :: * -> *).
MonadIO m =>
String -> String -> String -> m ()
renderQuestion String
question String
emptyString String
"no"
    forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
  else do
    forall (m :: * -> *).
MonadIO m =>
String -> String -> String -> m ()
renderQuestion String
question String
emptyString String
"yes"
    forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
  where
    defaultAnswerHumanized :: String
defaultAnswerHumanized = if Bool
defaultAnswer then String
"yes" else String
"no"

-- | Ask a confirm question by default it will be true
confirm :: MonadIO m => String -> m Bool
confirm :: forall (m :: * -> *). MonadIO m => String -> m Bool
confirm String
question = forall (m :: * -> *). MonadIO m => String -> Bool -> m Bool
confirmWithDefault String
question Bool
False