{-|
Module      : ScreenListeners
Description : Módulo que estabelece ações e lógica das telas e de leitura de dados no sistema SIGES.
-}
module TUI.ScreenListeners(
    module TUI.ScreenListeners
) where

import qualified System.Console.Haskeline as Hkl
import qualified Data.Map as Map

import Manager
import TUI.OutputScreens
import Handlers.ErrorHandler
import Handlers.UserHandler
import Handlers.DataHandler
import Handlers.RoomsHandler

-- | Typeclass que estabelece as operações de ações a ser executadas em cada tela do sistema.
class Action a where
    useContent :: a -> IO Screen -- ^ A implementação de como a tela será impressa na tela e como lerá as informações dadas pelo usuário.

instance Action Screen where
    useContent :: Screen -> IO Screen
useContent Screen
ExitScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
ExitScreen
        IO Screen
forall a. IO a
exitSuccess

    useContent Screen
FirstScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
FirstScreen
        String -> IO ()
putStrLn String
"Qual o e-mail do novo usuário?"
        String
email <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkNewEmail
        if String
email String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"Retornar"
            then Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
StartScreen
            else do
                String -> IO ()
putStrLn String
"Qual é a senha do novo usuário?"
                String
password <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getPassword String -> IO (Either String String)
checkNewPass
                String -> IO ()
putStrLn String
"Qual o nome do novo usuário?"
                String
name <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkName
                String -> String -> String -> Bool -> IO ()
registerNewUser String
email String
password String
name Bool
True
                Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
AdminScreen

    useContent Screen
StartScreen = do
        IO ()
signOutUser
        IO Bool
cleanAllReservations
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
StartScreen
        IO String -> (String -> IO (Either String Screen)) -> IO Screen
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer (Screen -> String -> IO (Either String Screen)
validScreen Screen
StartScreen)

    useContent Screen
LoginScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
LoginScreen
        String -> IO ()
putStrLn String
"Qual é o seu e-mail?"
        String
email <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkEmail
        if String
email String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"Retornar"
            then Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
StartScreen
            else do
                String -> IO ()
putStrLn String
"Qual é a sua senha?"
                String
password <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getPassword (String -> String -> IO (Either String String)
checkPass String
email)
                String -> IO ()
signUser String
email
                Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
LoggedScreen

    useContent Screen
LoggedScreen  = do
        User
user <- IO User
getLoggedUser
        let userScreen :: Screen
userScreen = if User -> Bool
isAdminUser User
user then Screen
AdminScreen else Screen
LoggedScreen
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
userScreen
        IO String -> (String -> IO (Either String Screen)) -> IO Screen
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer (Screen -> String -> IO (Either String Screen)
validScreen Screen
userScreen)

    useContent Screen
AdminScreen = Screen -> IO Screen
forall a. Action a => a -> IO Screen
useContent Screen
LoggedScreen

    useContent Screen
InsertRoomScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
InsertRoomScreen
        String -> IO ()
putStrLn String
"Qual o nome/código da sala a ser criada?"
        String
code <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkNewRoomCode
        IO ()
printCategories
        RoomCategory
category <- IO String
-> (String -> IO (Either String RoomCategory)) -> IO RoomCategory
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String RoomCategory)
checkCategory
        [Resource]
resources <- IO [Resource]
getResources
        String -> IO ()
putStrLn String
"Qual a capacidade da sala a ser criada?"
        Int
capacity <- IO String -> (String -> IO (Either String Int)) -> IO Int
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Int)
checkNumber
        String -> IO ()
putStrLn String
"Qual a localização da sala a ser criada?"
        String
location <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer (Either String String -> IO (Either String String)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String String -> IO (Either String String))
-> (String -> Either String String)
-> String
-> IO (Either String String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Either String String
forall a b. b -> Either a b
Right)
        String -> [Resource] -> RoomCategory -> Int -> String -> IO Bool
createRoom String
code [Resource]
resources RoomCategory
category Int
capacity String
location
        String -> IO ()
putStr String
"Sala criada! "
        IO String
waitInput
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
LoggedScreen

    useContent Screen
SignUpScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
SignUpScreen
        String -> IO ()
putStrLn String
"Qual o e-mail do novo usuário?"
        String
email <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkNewEmail
        if String
email String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"Retornar"
            then Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
LoggedScreen
            else do
                String -> IO ()
putStrLn String
"Qual é a senha do novo usuário?"
                String
password <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getPassword String -> IO (Either String String)
checkNewPass
                String -> IO ()
putStrLn String
"Qual o nome do novo usuário?"
                String
name <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkName
                String -> IO ()
putStrLn String
"Este usuário é administrador (S/N)?"
                Bool
isAdm <- IO String -> (String -> IO (Either String Bool)) -> IO Bool
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Bool)
yesOrNo
                String -> String -> String -> Bool -> IO ()
registerNewUser String
email String
password String
name Bool
isAdm
                Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
LoggedScreen

    useContent Screen
RemoveUserScreen = do
        User
admUser <- IO User
getLoggedUser
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
RemoveUserScreen
        String -> IO ()
putStrLn String
"Qual o e-mail do usuário a ser deletado?"
        String
email <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkEmail
        if String
email String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"Retornar" then () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            else do
                User
currentUser <- String -> IO User
retrieveUser String
email
                User -> IO ()
forall a. Show a => a -> IO ()
print User
currentUser
                String -> IO ()
putStrLn String
"Insira sua senha para confirmar:"
                String
admPassword <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getPassword ((String -> IO (Either String String)) -> IO String)
-> (String -> IO (Either String String)) -> IO String
forall a b. (a -> b) -> a -> b
$ String -> String -> IO (Either String String)
checkPass (User -> String
emailUser User
admUser)
                User -> IO ()
removeUser User
currentUser
                String -> IO ()
putStrLn String
"Usuário removido!"
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
LoggedScreen

    useContent Screen
ViewUserScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
ViewUserScreen
        User
user <- IO User
getLoggedUser
        [Room]
rooms <- String -> IO [Room]
searchRoomsRequester (String -> IO [Room]) -> String -> IO [Room]
forall a b. (a -> b) -> a -> b
$ User -> String
nameUser User
user
        if [Room] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Room]
rooms
            then String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Sem dados de salas encontrados para "String -> String -> String
forall a. [a] -> [a] -> [a]
++ User -> String
nameUser User
user
            else (Room -> IO ()) -> [Room] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Room -> IO ()
forall a. Show a => a -> IO ()
print [Room]
rooms
        String -> IO ()
putStrLn String
"\nDeseja visualizar de outras formas/alguma sala específica [S/N]?"
        Bool
more <- IO String -> (String -> IO (Either String Bool)) -> IO Bool
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Bool)
yesOrNo
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return (Screen -> IO Screen) -> Screen -> IO Screen
forall a b. (a -> b) -> a -> b
$ if Bool
more then Screen
ViewScreen else Screen
LoggedScreen

    useContent Screen
ViewScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
ViewScreen
        Screen
screen <- IO String -> (String -> IO (Either String Screen)) -> IO Screen
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer (Screen -> String -> IO (Either String Screen)
validScreen Screen
ViewScreen)
        Bool
loggedUser <- IO Bool
hasLoggedUser
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return (Screen -> IO Screen) -> Screen -> IO Screen
forall a b. (a -> b) -> a -> b
$ if Screen
screen Screen -> Screen -> Bool
forall a. Eq a => a -> a -> Bool
== Screen
StartScreen Bool -> Bool -> Bool
&& Bool
loggedUser then Screen
LoggedScreen else Screen
screen

    useContent Screen
ViewRoomScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
ViewRoomScreen
        String -> IO ()
putStrLn String
"Qual o código/nome da sala que você quer visualizar?"
        String
roomCode <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkRoomCode
        (Just Room
room) <- String -> IO (Maybe Room)
getRoom String
roomCode
        Room -> IO ()
forall a. Show a => a -> IO ()
print Room
room
        IO String
waitInput
        Bool
userLogged <- IO Bool
hasLoggedUser
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return (Screen -> IO Screen) -> Screen -> IO Screen
forall a b. (a -> b) -> a -> b
$ if Bool
userLogged then Screen
LoggedScreen else Screen
StartScreen

    useContent Screen
ViewFilterScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
ViewFilterScreen
        [Room]
rooms <- [Room] -> IO [Room]
getRoomsFilter []
        if [Room] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Room]
rooms
            then String -> IO ()
putStrLn String
"Sem dados de salas encontrados\n"
            else (Room -> IO ()) -> [Room] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Room -> IO ()
forall a. Show a => a -> IO ()
print [Room]
rooms
        IO String
waitInput
        Bool
userLogged <- IO Bool
hasLoggedUser
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return (Screen -> IO Screen) -> Screen -> IO Screen
forall a b. (a -> b) -> a -> b
$ if Bool
userLogged then Screen
LoggedScreen else Screen
StartScreen

    useContent Screen
ReportRoomScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
ReportRoomScreen
        String -> IO ()
putStrLn String
"Qual o código/nome da sala que você quer visualizar?"
        String
roomCode <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkRoomCode
        (Just Room
room) <- String -> IO (Maybe Room)
getRoom String
roomCode
        String -> IO ()
putStrLn String
"Qual o dia de ocupação você deseja ver [DD-MM-AAAA]?"
        [Int
y,Int
m,Int
d] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkDay
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ (Integer, Int, Int) -> Room -> String
createReportForTheRoom (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
y, Int
m, Int
d) Room
room
        IO String
waitInput
        Bool
userLogged <- IO Bool
hasLoggedUser
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return (Screen -> IO Screen) -> Screen -> IO Screen
forall a b. (a -> b) -> a -> b
$ if Bool
userLogged then Screen
LoggedScreen else Screen
StartScreen

    useContent Screen
ReportDayScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
ReportDayScreen
        String -> IO ()
putStrLn String
"Qual o dia de ocupação você deseja ver [DD-MM-AAAA]?"
        [Int
y,Int
m,Int
d] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkDay
        String
report <- (Integer, Int, Int) -> IO String
createReportForTheDay (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
y, Int
m, Int
d)
        String -> IO ()
putStrLn String
report
        IO String
waitInput
        Bool
userLogged <- IO Bool
hasLoggedUser
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return (Screen -> IO Screen) -> Screen -> IO Screen
forall a b. (a -> b) -> a -> b
$ if Bool
userLogged then Screen
LoggedScreen else Screen
StartScreen

    useContent Screen
CreateReservationScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
CreateReservationScreen
        String -> IO ()
putStrLn String
"Qual o código/nome da sala que você quer reservar?"
        String
roomCode <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkRoomCode
        String -> IO ()
putStrLn String
"Qual o dia da reserva [DD-MM-AAAA]?"
        [Int
y,Int
m,Int
d] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkDay
        String -> IO ()
putStrLn String
"Qual o horário de início [HH:MM]?"
        [Int
hStart, Int
mStart] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkTime
        String -> IO ()
putStrLn String
"Qual o horário de término [HH:MM]?"
        [Int
hEnd, Int
mEnd] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkTime
        String -> IO ()
putStrLn String
"Dê uma breve descrição sobre a reserva"
        String
description <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkDescription

        User
user <- IO User
getLoggedUser
        Bool
created <- String
-> String
-> String
-> (Integer, Int, Int, Int, Int)
-> (Integer, Int, Int, Int, Int)
-> IO Bool
makeReservation String
roomCode (User -> String
nameUser User
user) String
description (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
y,Int
m,Int
d,Int
hStart,Int
mStart) (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
y,Int
m,Int
d,Int
hEnd,Int
mEnd)
        if Bool
created
            then String -> IO ()
putStr String
"Reserva criada! "
            else String -> IO ()
putStr String
"Sala já ocupada neste horário. "
        IO String
waitInput
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
LoggedScreen

    useContent Screen
EditReservationScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
EditReservationScreen
        String -> IO ()
putStrLn String
"Qual o código/nome da sala que você quer editar a reserva?"
        String
roomCode <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkRoomCode
        String -> IO ()
putStrLn String
"Qual o dia da reserva feita [DD-MM-AAAA]?"
        [Int
yOld,Int
mOld,Int
dOld] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkDay
        String -> IO ()
putStrLn String
"Qual o horário de início da reserva feita [HH:MM]?"
        [Int
hOldStart, Int
minOldStart] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkTime
        String -> IO ()
putStrLn String
"Qual o novo dia da reserva [DD-MM-AAAA]?"
        [Int
yNew,Int
mNew,Int
dNew] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkDay
        String -> IO ()
putStrLn String
"Qual o novo horário de início da reserva [HH:MM]?"
        [Int
hNewStart, Int
minNewStart] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkTime
        String -> IO ()
putStrLn String
"Qual o novo horário de término da reserva [HH:MM]?"
        [Int
hNewEnd, Int
minNewEnd] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkTime

        User
user <- IO User
getLoggedUser
        Bool
edited <- String
-> String
-> (Integer, Int, Int, Int, Int)
-> (Integer, Int, Int, Int, Int)
-> (Integer, Int, Int, Int, Int)
-> IO Bool
editReservation String
roomCode (User -> String
nameUser User
user) (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
yOld,Int
mOld,Int
dOld,Int
hOldStart,Int
minOldStart) (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
yNew,Int
mNew,Int
dNew,Int
hNewStart,Int
minNewStart) (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
yNew,Int
mNew,Int
dNew,Int
hNewEnd,Int
minNewEnd)
        if Bool
edited
            then String -> IO ()
putStrLn String
"Reserva editada! "
            else String -> IO ()
putStrLn String
"A reserva não existe ou já está ocupada no novo horário. "
        IO String
waitInput
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
LoggedScreen

    useContent Screen
RemoveReservationScreen = do
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Screen -> String
forall a. Content a => a -> String
getContent Screen
RemoveReservationScreen
        String -> IO ()
putStrLn String
"Qual o código/nome da sala que você quer remover a reserva?"
        String
roomCode <- IO String -> (String -> IO (Either String String)) -> IO String
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String String)
checkRoomCode
        String -> IO ()
putStrLn String
"Qual o dia da reserva feita [DD-MM-AAAA]?"
        [Int
y,Int
m,Int
d] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkDay
        String -> IO ()
putStrLn String
"Qual o horário de início da reserva feita [HH:MM]?"
        [Int
hStart, Int
minStart] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkTime

        User
user <- IO User
getLoggedUser
        Reservation
reservation <- String -> (Integer, Int, Int, Int, Int) -> String -> IO Reservation
findReservation String
roomCode (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
y,Int
m,Int
d,Int
hStart,Int
minStart) (User -> String
nameUser User
user)
        Reservation -> IO ()
forall a. Show a => a -> IO ()
print Reservation
reservation
        String -> IO ()
putStrLn String
"Confirma a deleção da reserva acima [S/N]?"
        Bool
toDelete <- IO String -> (String -> IO (Either String Bool)) -> IO Bool
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Bool)
yesOrNo
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
toDelete (do
                String -> String -> (Integer, Int, Int, Int, Int) -> IO Bool
deleteReservation String
roomCode (User -> String
nameUser User
user) (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
y,Int
m,Int
d,Int
hStart,Int
minStart)
                String -> IO ()
putStrLn String
"Reserva deletada. "
                IO String
waitInput
                () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return())
        Screen -> IO Screen
forall (m :: * -> *) a. Monad m => a -> m a
return Screen
LoggedScreen

-- | Esta é a função responsável por encontrar e controlar quais telas serão exibidas no sistema SIGES.
userInteraction :: Screen -> IO Screen
userInteraction :: Screen -> IO Screen
userInteraction Screen
screen = do
    Bool
firstAccess <- IO Bool
noUsersYet
    let currentScreen :: Screen
currentScreen = if Bool
firstAccess then Screen
FirstScreen else Screen
screen

    Screen -> IO Screen
forall a. Action a => a -> IO Screen
useContent Screen
currentScreen

waitInput :: IO String
waitInput :: IO String
waitInput = do
    String -> IO ()
putStrLn String
"Aperte qualquer tecla para continuar"
    IO String
getLine

-- | Esta função exibirá um prompt e captará a resposta digitada pelo usuário.
getAnswer :: IO String
getAnswer :: IO String
getAnswer = do
    String -> IO ()
putStr String
">> "
    Handle -> IO ()
hFlush Handle
stdout
    IO String
getLine

-- | Função responsável por captar a senha do usuário da entrada e garantir que ela seja exibida apenas com asteriscos, como forma de melhorar a segurança.
getPassword :: IO String
getPassword :: IO String
getPassword = Settings IO -> InputT IO String -> IO String
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
Settings m -> InputT m a -> m a
Hkl.runInputT Settings IO
forall (m :: * -> *). MonadIO m => Settings m
Hkl.defaultSettings (InputT IO String -> IO String) -> InputT IO String -> IO String
forall a b. (a -> b) -> a -> b
$ do {Maybe String
p <- Maybe Char -> String -> InputT IO (Maybe String)
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
Maybe Char -> String -> InputT m (Maybe String)
Hkl.getPassword (Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'*') String
">> "; String -> InputT IO String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> InputT IO String) -> String -> InputT IO String
forall a b. (a -> b) -> a -> b
$ Maybe String -> String
forall a. HasCallStack => Maybe a -> a
fromJust Maybe String
p}

-- | Dada uma Mônada de String qualquer e uma função de verificação, esta função aplicará a função sobre a String. Caso a String passe na verificação fornecida, será retornada. Caso contrário, uma mensagem de erro será exibida e a função será repetida com uma nova entrada.
getInputData :: IO String -> (String -> IO (Either ErrorLog a)) -> IO a
getInputData :: IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getter String -> IO (Either String a)
checker = do
    String
input <- IO String
getter
    Either String a
checkedAnswer <- String -> IO (Either String a)
checker String
input
    case Either String a
checkedAnswer of
        Left String
error -> do {String -> IO ()
putStrLn String
error; IO String -> (String -> IO (Either String a)) -> IO a
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getter String -> IO (Either String a)
checker}
        Right a
answer -> a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
answer

-- | Esta filtrará salas pelos filtros escolhidos pelo usuário. MAis de um filtro podem ser aplicados simultaneamente, neste caso, a função perguntará um a um quais filtros devem ser adicionados.
getRoomsFilter :: [Room] -> IO [Room]
getRoomsFilter :: [Room] -> IO [Room]
getRoomsFilter [Room]
previous = do
    String -> IO ()
putStrLn String
"Por qual critério você deseja filtrar?\n\
              \1 - Categoria\n\
              \2 - Capacidade\n\
              \3 - Horário\n\
              \4 - Recursos"
    Int
option <- IO String -> (String -> IO (Either String Int)) -> IO Int
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Int)
checkFilter
    [Room]
rooms <- case Int
option of
                Int
1 -> do
                    IO ()
printCategories
                    RoomCategory
cat <- IO String
-> (String -> IO (Either String RoomCategory)) -> IO RoomCategory
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String RoomCategory)
checkCategory
                    RoomCategory -> IO [Room]
searchRoomsCategory RoomCategory
cat
                Int
2 -> do
                    String -> IO ()
putStrLn String
"Capacidade mínima desejada: "
                    Int
cap <- IO String -> (String -> IO (Either String Int)) -> IO Int
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Int)
checkNumber
                    Int -> IO [Room]
searchRoomsCapacity Int
cap
                Int
3 -> do
                    String -> IO ()
putStrLn String
"Qual o dia a ser buscado [DD-MM-AAAA]?"
                    [Int
y,Int
m,Int
d] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkDay
                    String -> IO ()
putStrLn String
"Qual o horário de início a ser buscado [HH:MM]?"
                    [Int
hStart, Int
minStart] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkTime
                    String -> IO ()
putStrLn String
"Qual o horário de término a ser buscado [HH:MM]?"
                    [Int
hEnd, Int
minEnd] <- IO String -> (String -> IO (Either String [Int])) -> IO [Int]
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String [Int])
checkTime
                    (Integer, Int, Int, Int, Int)
-> (Integer, Int, Int, Int, Int) -> IO [Room]
searchRoomsTime (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
y, Int
m, Int
d, Int
hStart, Int
minStart) (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
y,Int
m,Int
d,Int
hEnd,Int
minEnd)
                Int
4 -> do
                    [Resource]
resources <- IO [Resource]
getResources
                    [Resource] -> IO [Room]
searchRoomsResources [Resource]
resources

    let intersected :: [Room]
intersected = if [Room] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Room]
previous then [Room]
rooms else [Room]
rooms [Room] -> [Room] -> [Room]
forall a. Eq a => [a] -> [a] -> [a]
`intersect` [Room]
previous
    String -> IO ()
putStrLn String
"Deseja combinar sua busca com outro filtro [S/N]?"
    Bool
more <- IO String -> (String -> IO (Either String Bool)) -> IO Bool
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Bool)
yesOrNo
    if Bool
more then [Room] -> IO [Room]
getRoomsFilter [Room]
intersected else [Room] -> IO [Room]
forall (m :: * -> *) a. Monad m => a -> m a
return [Room]
intersected

-- | Função auxiliar à função de filtro de salas. Esta função lerá da entrada recursos que o usuário deseja buscar e suas respectivas quantidades, e então produzirá uma lista de recursos com estas informações e a retornará.
{-getResources :: [Resource] -> IO [Resource]
getResources previous = do
    kind <- getInputData getAnswer checkResource
    putStrLn "Qual a quantidade desejada/existente do recurso?"
    quantity <- getInputData getAnswer checkNumber
    let resources = previous ++ [Resource kind quantity]
    putStrLn "Deseja buscar mais recursos [S/N]?"
    more <- getInputData getAnswer yesOrNo
    if more then getResources resources else return resources-}

getResources :: IO [Resource]
getResources :: IO [Resource]
getResources = do
    let action :: IO Resource
action = do {
        IO ()
printResources;
        ResourceKind
kind <- IO String
-> (String -> IO (Either String ResourceKind)) -> IO ResourceKind
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String ResourceKind)
checkResource;
        String -> IO ()
putStrLn String
"Qual a quantidade desejada/existente do recurso?";
        Int
quantity <- IO String -> (String -> IO (Either String Int)) -> IO Int
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Int)
checkNumber;
        String -> IO ()
putStrLn String
"Deseja buscar mais recursos [S/N]?";
        Resource -> IO Resource
forall (m :: * -> *) a. Monad m => a -> m a
return (Resource -> IO Resource) -> Resource -> IO Resource
forall a b. (a -> b) -> a -> b
$ ResourceKind -> Int -> Resource
Resource ResourceKind
kind Int
quantity
    }
    Resource
firstResource <- IO Resource
action
    [Resource]
nextResources <- IO Bool -> IO Resource -> IO [Resource]
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m [a]
whileM (IO String -> (String -> IO (Either String Bool)) -> IO Bool
forall a. IO String -> (String -> IO (Either String a)) -> IO a
getInputData IO String
getAnswer String -> IO (Either String Bool)
yesOrNo) IO Resource
action
    [Resource] -> IO [Resource]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Resource] -> IO [Resource]) -> [Resource] -> IO [Resource]
forall a b. (a -> b) -> a -> b
$ Resource
firstResourceResource -> [Resource] -> [Resource]
forall a. a -> [a] -> [a]
:[Resource]
nextResources