module Taskell.Events.State.Modal.Detail
    ( updateField
    , finishSubtask
    , finishDescription
    , finishDue
    , showDetail
    , getCurrentItem
    , getCurrentMode
    , getField
    , setComplete
    , remove
    , insertMode
    , editDescription
    , editDue
    , newItem
    , nextSubtask
    , previousSubtask
    , lastSubtask
    , up
    , down
    ) where

import ClassyPrelude

import Control.Lens ((&), (.~), (^.))

import           Taskell.Data.Date               (timeToDisplay)
import qualified Taskell.Data.Seq                as S
import qualified Taskell.Data.Subtask            as ST (blank, name, toggle)
import           Taskell.Data.Task               (Task, addSubtask, countSubtasks, description, due,
                                                  getSubtask, removeSubtask, setDescription, setDue,
                                                  subtasks, updateSubtask)
import           Taskell.Events.State            (getCurrentTask, setCurrentTask)
import           Taskell.Events.State.Types      (State, Stateful, mode, time, timeZone)
import           Taskell.Events.State.Types.Mode (DetailItem (..), DetailMode (..),
                                                  ModalType (Detail), Mode (Modal))
import           Taskell.UI.Draw.Field           (Field, blankField, getText, textToField)

updateField :: (Field -> Field) -> Stateful
updateField :: (Field -> Field) -> Stateful
updateField Field -> Field
fieldEvent State
s =
    Stateful
forall (f :: * -> *) a. Applicative f => a -> f a
pure Stateful -> Stateful
forall a b. (a -> b) -> a -> b
$
    case State
s State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode of
        Modal (Detail DetailItem
detailItem (DetailInsert Field
field)) ->
            State
s State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail DetailItem
detailItem (Field -> DetailMode
DetailInsert (Field -> Field
fieldEvent Field
field)))
        Mode
_ -> State
s

finishSubtask :: Stateful
finishSubtask :: Stateful
finishSubtask State
state = do
    Text
text <- Field -> Text
getText (Field -> Text) -> Maybe Field -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Field
getField State
state
    Int
i <- State -> Maybe Int
getCurrentSubtask State
state
    Task
task <- Int -> Update -> Update
updateSubtask Int
i ((Text -> Identity Text) -> Subtask -> Identity Subtask
Lens' Subtask Text
ST.name ((Text -> Identity Text) -> Subtask -> Identity Subtask)
-> Text -> Update
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Text
text) Update -> Maybe Task -> Maybe Task
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Task
getCurrentTask State
state
    Task -> Stateful
setCurrentTask Task
task Stateful -> Stateful
forall a b. (a -> b) -> a -> b
$ State
state State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail (Int -> DetailItem
DetailItem Int
i) (Field -> DetailMode
DetailInsert Field
blankField))

finish :: (Text -> Task -> Task) -> Stateful
finish :: (Text -> Update) -> Stateful
finish Text -> Update
fn State
state = do
    Text
text <- Field -> Text
getText (Field -> Text) -> Maybe Field -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Field
getField State
state
    Task
task <- Text -> Update
fn Text
text Update -> Maybe Task -> Maybe Task
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Task
getCurrentTask State
state
    Task -> Stateful
setCurrentTask Task
task Stateful -> Stateful
forall a b. (a -> b) -> a -> b
$ State
state State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail (Int -> DetailItem
DetailItem Int
0) DetailMode
DetailNormal)

finishDescription :: Stateful
finishDescription :: Stateful
finishDescription = (Text -> Update) -> Stateful
finish Text -> Update
setDescription

finishDue :: Stateful
finishDue :: Stateful
finishDue State
state = do
    let tz :: TZ
tz = State
state State -> Getting TZ State TZ -> TZ
forall s a. s -> Getting a s a -> a
^. Getting TZ State TZ
Lens' State TZ
timeZone
    let now :: UTCTime
now = State
state State -> Getting UTCTime State UTCTime -> UTCTime
forall s a. s -> Getting a s a -> a
^. Getting UTCTime State UTCTime
Lens' State UTCTime
time
    Text
text <- Field -> Text
getText (Field -> Text) -> Maybe Field -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Field
getField State
state
    Task
task <- TZ -> UTCTime -> Text -> Task -> Maybe Task
setDue TZ
tz UTCTime
now Text
text (Task -> Maybe Task) -> Maybe Task -> Maybe Task
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< State -> Maybe Task
getCurrentTask State
state
    Task -> Stateful
setCurrentTask Task
task Stateful -> Stateful
forall a b. (a -> b) -> a -> b
$ State
state State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail (Int -> DetailItem
DetailItem Int
0) DetailMode
DetailNormal)

showDetail :: Stateful
showDetail :: Stateful
showDetail State
s = do
    Task
_ <- State -> Maybe Task
getCurrentTask State
s
    let i :: Int
i = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ State -> Maybe Int
getCurrentSubtask State
s
    Stateful
forall (f :: * -> *) a. Applicative f => a -> f a
pure Stateful -> Stateful
forall a b. (a -> b) -> a -> b
$ State
s State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail (Int -> DetailItem
DetailItem Int
i) DetailMode
DetailNormal)

getCurrentSubtask :: State -> Maybe Int
getCurrentSubtask :: State -> Maybe Int
getCurrentSubtask State
state =
    case State
state State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode of
        Modal (Detail (DetailItem Int
i) DetailMode
_) -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
i
        Mode
_                               -> Maybe Int
forall a. Maybe a
Nothing

getCurrentItem :: State -> Maybe DetailItem
getCurrentItem :: State -> Maybe DetailItem
getCurrentItem State
state =
    case State
state State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode of
        Modal (Detail DetailItem
item DetailMode
_) -> DetailItem -> Maybe DetailItem
forall a. a -> Maybe a
Just DetailItem
item
        Mode
_                     -> Maybe DetailItem
forall a. Maybe a
Nothing

getCurrentMode :: State -> Maybe DetailMode
getCurrentMode :: State -> Maybe DetailMode
getCurrentMode State
state =
    case State
state State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode of
        Modal (Detail DetailItem
_ DetailMode
m) -> DetailMode -> Maybe DetailMode
forall a. a -> Maybe a
Just DetailMode
m
        Mode
_                  -> Maybe DetailMode
forall a. Maybe a
Nothing

getField :: State -> Maybe Field
getField :: State -> Maybe Field
getField State
state =
    case State
state State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode of
        Modal (Detail DetailItem
_ (DetailInsert Field
f)) -> Field -> Maybe Field
forall a. a -> Maybe a
Just Field
f
        Mode
_                                 -> Maybe Field
forall a. Maybe a
Nothing

setComplete :: Stateful
setComplete :: Stateful
setComplete State
state = do
    Int
i <- State -> Maybe Int
getCurrentSubtask State
state
    Task
task <- Int -> Update -> Update
updateSubtask Int
i Update
ST.toggle Update -> Maybe Task -> Maybe Task
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Task
getCurrentTask State
state
    Task -> Stateful
setCurrentTask Task
task State
state

remove :: Stateful
remove :: Stateful
remove State
state = do
    Int
i <- State -> Maybe Int
getCurrentSubtask State
state
    Task
task <- Int -> Update
removeSubtask Int
i Update -> Maybe Task -> Maybe Task
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Task
getCurrentTask State
state
    State
state' <- Task -> Stateful
setCurrentTask Task
task State
state
    State -> Int -> Maybe State
setIndex State
state' Int
i

insertMode :: Stateful
insertMode :: Stateful
insertMode State
state = do
    Int
i <- State -> Maybe Int
getCurrentSubtask State
state
    Task
task <- State -> Maybe Task
getCurrentTask State
state
    Text
n <- (Subtask -> Getting Text Subtask Text -> Text
forall s a. s -> Getting a s a -> a
^. Getting Text Subtask Text
Lens' Subtask Text
ST.name) (Subtask -> Text) -> Maybe Subtask -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Task -> Maybe Subtask
getSubtask Int
i Task
task
    case State
state State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode of
        Modal (Detail (DetailItem Int
i') DetailMode
_) ->
            Stateful
forall a. a -> Maybe a
Just (State
state State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail (Int -> DetailItem
DetailItem Int
i') (Field -> DetailMode
DetailInsert (Text -> Field
textToField Text
n))))
        Mode
_ -> Maybe State
forall a. Maybe a
Nothing

editDescription :: Stateful
editDescription :: Stateful
editDescription State
state = do
    Maybe Text
summ <- (Task -> Getting (Maybe Text) Task (Maybe Text) -> Maybe Text
forall s a. s -> Getting a s a -> a
^. Getting (Maybe Text) Task (Maybe Text)
Lens' Task (Maybe Text)
description) (Task -> Maybe Text) -> Maybe Task -> Maybe (Maybe Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Task
getCurrentTask State
state
    let summ' :: Text
summ' = Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"" Maybe Text
summ
    Stateful
forall (f :: * -> *) a. Applicative f => a -> f a
pure Stateful -> Stateful
forall a b. (a -> b) -> a -> b
$ State
state State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail DetailItem
DetailDescription (Field -> DetailMode
DetailInsert (Text -> Field
textToField Text
summ')))

editDue :: Stateful
editDue :: Stateful
editDue State
state = do
    Maybe Due
day <- (Task -> Getting (Maybe Due) Task (Maybe Due) -> Maybe Due
forall s a. s -> Getting a s a -> a
^. Getting (Maybe Due) Task (Maybe Due)
Lens' Task (Maybe Due)
due) (Task -> Maybe Due) -> Maybe Task -> Maybe (Maybe Due)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Task
getCurrentTask State
state
    let tz :: TZ
tz = State
state State -> Getting TZ State TZ -> TZ
forall s a. s -> Getting a s a -> a
^. Getting TZ State TZ
Lens' State TZ
timeZone
    let day' :: Text
day' = Text -> (Due -> Text) -> Maybe Due -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (TZ -> Due -> Text
timeToDisplay TZ
tz) Maybe Due
day
    Stateful
forall (f :: * -> *) a. Applicative f => a -> f a
pure Stateful -> Stateful
forall a b. (a -> b) -> a -> b
$ State
state State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail DetailItem
DetailDate (Field -> DetailMode
DetailInsert (Text -> Field
textToField Text
day')))

newItem :: Stateful
newItem :: Stateful
newItem State
state = do
    Task
task <- Subtask -> Update
addSubtask Subtask
ST.blank Update -> Maybe Task -> Maybe Task
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Task
getCurrentTask State
state
    Task -> Stateful
setCurrentTask Task
task State
state

-- list navigation
changeSubtask :: Int -> Stateful
changeSubtask :: Int -> Stateful
changeSubtask Int
inc State
state = do
    Int
i <- (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
inc) (Int -> Int) -> Maybe Int -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Int
getCurrentSubtask State
state
    State -> Int -> Maybe State
setIndex State
state Int
i

nextSubtask :: Stateful
nextSubtask :: Stateful
nextSubtask = Int -> Stateful
changeSubtask Int
1

previousSubtask :: Stateful
previousSubtask :: Stateful
previousSubtask = Int -> Stateful
changeSubtask (-Int
1)

lastSubtask :: Stateful
lastSubtask :: Stateful
lastSubtask State
state = State -> Maybe Int
lastIndex State
state Maybe Int -> (Int -> Maybe State) -> Maybe State
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= State -> Int -> Maybe State
setIndex State
state

lastIndex :: State -> Maybe Int
lastIndex :: State -> Maybe Int
lastIndex State
state = (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (-Int
1)) (Int -> Int) -> (Task -> Int) -> Task -> Int
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Task -> Int
countSubtasks (Task -> Int) -> Maybe Task -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> State -> Maybe Task
getCurrentTask State
state

setIndex :: State -> Int -> Maybe State
setIndex :: State -> Int -> Maybe State
setIndex State
state Int
i = do
    Int
lst <- State -> Maybe Int
lastIndex State
state
    DetailMode
m <- State -> Maybe DetailMode
getCurrentMode State
state
    let newIndex :: Int
newIndex
            | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
lst = Int
lst
            | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Int
0
            | Bool
otherwise = Int
i
    Stateful
forall (m :: * -> *) a. Monad m => a -> m a
return Stateful -> Stateful
forall a b. (a -> b) -> a -> b
$ State
state State -> (State -> State) -> State
forall a b. a -> (a -> b) -> b
& (Mode -> Identity Mode) -> State -> Identity State
Lens' State Mode
mode ((Mode -> Identity Mode) -> State -> Identity State)
-> Mode -> State -> State
forall s t a b. ASetter s t a b -> b -> s -> t
.~ ModalType -> Mode
Modal (DetailItem -> DetailMode -> ModalType
Detail (Int -> DetailItem
DetailItem Int
newIndex) DetailMode
m)

-- moving tasks
moveVertical :: Int -> Stateful
moveVertical :: Int -> Stateful
moveVertical Int
dir State
state = do
    Task
task <- State -> Maybe Task
getCurrentTask State
state
    let tasks :: Seq Subtask
tasks = Task
task Task -> Getting (Seq Subtask) Task (Seq Subtask) -> Seq Subtask
forall s a. s -> Getting a s a -> a
^. Getting (Seq Subtask) Task (Seq Subtask)
Lens' Task (Seq Subtask)
subtasks
    Int
i <- State -> Maybe Int
getCurrentSubtask State
state
    Seq Subtask
shifted <- Int -> Int -> Seq Subtask -> Maybe (Seq Subtask)
forall a. Int -> Int -> Seq a -> Maybe (Seq a)
S.shiftBy Int
i Int
dir Seq Subtask
tasks
    State
state' <- Task -> Stateful
setCurrentTask (Task
task Task -> Update -> Task
forall a b. a -> (a -> b) -> b
& (Seq Subtask -> Identity (Seq Subtask)) -> Task -> Identity Task
Lens' Task (Seq Subtask)
subtasks ((Seq Subtask -> Identity (Seq Subtask)) -> Task -> Identity Task)
-> Seq Subtask -> Update
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Seq Subtask
shifted) State
state
    Int -> Stateful
changeSubtask Int
dir State
state'

up :: Stateful
up :: Stateful
up = Int -> Stateful
moveVertical (-Int
1)

down :: Stateful
down :: Stateful
down = Int -> Stateful
moveVertical Int
1