module Taskell.UI.Draw.Main.List
    ( renderList
    ) where

import ClassyPrelude

import Control.Lens ((^.))

import Data.Char     (chr, ord)
import Data.Sequence (mapWithIndex)

import Brick

import Taskell.Data.List          (List, tasks, title)
import Taskell.Events.State.Types (current, mode)
import Taskell.IO.Config.Layout   (columnPadding, columnWidth)
import Taskell.Types              (ListIndex (ListIndex), TaskIndex (TaskIndex))
import Taskell.UI.Draw.Field      (textField, widgetFromMaybe)
import Taskell.UI.Draw.Mode
import Taskell.UI.Draw.Task       (renderTask)
import Taskell.UI.Draw.Types      (DSWidget, DrawState (..), ReaderDrawState)
import Taskell.UI.Theme
import Taskell.UI.Types           (ResourceName (..))

-- | Gets the relevant column prefix - number in normal mode, letter in moveTo
columnPrefix :: Int -> Int -> ReaderDrawState Text
columnPrefix :: Int -> Int -> ReaderDrawState Text
columnPrefix Int
selectedList Int
i = do
    Mode
m <- (State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode) (State -> Mode)
-> ReaderT DrawState Identity State
-> ReaderT DrawState Identity Mode
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (DrawState -> State) -> ReaderT DrawState Identity State
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DrawState -> State
dsState
    if Mode -> Bool
moveTo Mode
m
        then do
            let col :: Char
col = Int -> Char
chr (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Char -> Int
ord Char
'a')
            Text -> ReaderDrawState Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ReaderDrawState Text) -> Text -> ReaderDrawState Text
forall a b. (a -> b) -> a -> b
$
                if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
selectedList Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
26
                    then Element Text -> Text
forall seq. MonoPointed seq => Element seq -> seq
singleton Char
Element Text
col Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
". "
                    else Text
""
        else do
            let col :: Int
col = Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
            Text -> ReaderDrawState Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ReaderDrawState Text) -> Text -> ReaderDrawState Text
forall a b. (a -> b) -> a -> b
$
                if Int
col Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
1 Bool -> Bool -> Bool
&& Int
col Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
9
                    then Int -> Text
forall a. Show a => a -> Text
tshow Int
col Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
". "
                    else Text
""

-- | Renders the title for a list
renderTitle :: Int -> List -> DSWidget
renderTitle :: Int -> List -> DSWidget
renderTitle Int
listIndex List
list = do
    (ListIndex Int
selectedList, TaskIndex Int
selectedTask) <- (State
-> Getting (ListIndex, TaskIndex) State (ListIndex, TaskIndex)
-> (ListIndex, TaskIndex)
forall s a. s -> Getting a s a -> a
^. Getting (ListIndex, TaskIndex) State (ListIndex, TaskIndex)
Lens' State (ListIndex, TaskIndex)
current) (State -> (ListIndex, TaskIndex))
-> ReaderT DrawState Identity State
-> ReaderT DrawState Identity (ListIndex, TaskIndex)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (DrawState -> State) -> ReaderT DrawState Identity State
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DrawState -> State
dsState
    Bool
editing <- (Int
selectedList Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
listIndex Bool -> Bool -> Bool
&&) (Bool -> Bool) -> (State -> Bool) -> State -> Bool
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Mode -> Bool
editingTitle (Mode -> Bool) -> (State -> Mode) -> State -> Bool
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode) (State -> Bool)
-> ReaderT DrawState Identity State
-> ReaderT DrawState Identity Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (DrawState -> State) -> ReaderT DrawState Identity State
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DrawState -> State
dsState
    Maybe Field
titleField <- Mode -> Maybe Field
getField (Mode -> Maybe Field) -> (State -> Mode) -> State -> Maybe Field
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode) (State -> Maybe Field)
-> ReaderT DrawState Identity State
-> ReaderT DrawState Identity (Maybe Field)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (DrawState -> State) -> ReaderT DrawState Identity State
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DrawState -> State
dsState
    Widget ResourceName
col <- Text -> Widget ResourceName
forall n. Text -> Widget n
txt (Text -> Widget ResourceName) -> ReaderDrawState Text -> DSWidget
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Int -> ReaderDrawState Text
columnPrefix Int
selectedList Int
listIndex
    let text :: Text
text = List
list List -> Getting Text List Text -> Text
forall s a. s -> Getting a s a -> a
^. Getting Text List Text
Lens' List Text
title
        attr :: AttrName
attr =
            if Int
selectedList Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
listIndex
                then AttrName
titleCurrentAttr
                else AttrName
titleAttr
        widget :: Widget ResourceName
widget = Text -> Widget ResourceName
textField Text
text
        widget' :: Widget ResourceName
widget' = Widget ResourceName -> Maybe Field -> Widget ResourceName
widgetFromMaybe Widget ResourceName
widget Maybe Field
titleField
        title' :: Widget ResourceName
title' =
            Padding -> Widget ResourceName -> Widget ResourceName
forall n. Padding -> Widget n -> Widget n
padBottom (Int -> Padding
Pad Int
1) (Widget ResourceName -> Widget ResourceName)
-> (Widget ResourceName -> Widget ResourceName)
-> Widget ResourceName
-> Widget ResourceName
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. AttrName -> Widget ResourceName -> Widget ResourceName
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
attr (Widget ResourceName -> Widget ResourceName)
-> (Widget ResourceName -> Widget ResourceName)
-> Widget ResourceName
-> Widget ResourceName
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Widget ResourceName
col Widget ResourceName -> Widget ResourceName -> Widget ResourceName
forall n. Widget n -> Widget n -> Widget n
<+>) (Widget ResourceName -> Widget ResourceName)
-> Widget ResourceName -> Widget ResourceName
forall a b. (a -> b) -> a -> b
$
            if Bool
editing
                then Widget ResourceName
widget'
                else Widget ResourceName
widget
    Widget ResourceName -> DSWidget
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Widget ResourceName -> DSWidget)
-> Widget ResourceName -> DSWidget
forall a b. (a -> b) -> a -> b
$
        if Bool
editing Bool -> Bool -> Bool
|| Int
selectedList Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
listIndex Bool -> Bool -> Bool
|| Int
selectedTask Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
            then Widget ResourceName -> Widget ResourceName
forall n. Widget n -> Widget n
visible Widget ResourceName
title'
            else Widget ResourceName
title'

-- | Renders a list
renderList :: Int -> List -> DSWidget
renderList :: Int -> List -> DSWidget
renderList Int
listIndex List
list = do
    Config
layout <- DrawState -> Config
dsLayout (DrawState -> Config)
-> ReaderT DrawState Identity DrawState
-> ReaderT DrawState Identity Config
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT DrawState Identity DrawState
forall r (m :: * -> *). MonadReader r m => m r
ask
    Bool
eTitle <- Mode -> Bool
editingTitle (Mode -> Bool) -> (State -> Mode) -> State -> Bool
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (State -> Getting Mode State Mode -> Mode
forall s a. s -> Getting a s a -> a
^. Getting Mode State Mode
Lens' State Mode
mode) (State -> Bool)
-> ReaderT DrawState Identity State
-> ReaderT DrawState Identity Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (DrawState -> State) -> ReaderT DrawState Identity State
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DrawState -> State
dsState
    Widget ResourceName
titleWidget <- Int -> List -> DSWidget
renderTitle Int
listIndex List
list
    (ListIndex Int
currentList, TaskIndex
_) <- (State
-> Getting (ListIndex, TaskIndex) State (ListIndex, TaskIndex)
-> (ListIndex, TaskIndex)
forall s a. s -> Getting a s a -> a
^. Getting (ListIndex, TaskIndex) State (ListIndex, TaskIndex)
Lens' State (ListIndex, TaskIndex)
current) (State -> (ListIndex, TaskIndex))
-> ReaderT DrawState Identity State
-> ReaderT DrawState Identity (ListIndex, TaskIndex)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (DrawState -> State) -> ReaderT DrawState Identity State
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DrawState -> State
dsState
    Seq (Widget ResourceName)
taskWidgets <-
        Seq DSWidget
-> ReaderT DrawState Identity (Seq (Widget ResourceName))
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence (Seq DSWidget
 -> ReaderT DrawState Identity (Seq (Widget ResourceName)))
-> Seq DSWidget
-> ReaderT DrawState Identity (Seq (Widget ResourceName))
forall a b. (a -> b) -> a -> b
$
        (Int -> ResourceName) -> Int -> Int -> Task -> DSWidget
renderTask ((ListIndex, TaskIndex) -> ResourceName
RNTask ((ListIndex, TaskIndex) -> ResourceName)
-> (Int -> (ListIndex, TaskIndex)) -> Int -> ResourceName
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Int -> ListIndex
ListIndex Int
listIndex, ) (TaskIndex -> (ListIndex, TaskIndex))
-> (Int -> TaskIndex) -> Int -> (ListIndex, TaskIndex)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int -> TaskIndex
TaskIndex) Int
listIndex (Int -> Task -> DSWidget) -> Seq Task -> Seq DSWidget
forall a b. (Int -> a -> b) -> Seq a -> Seq b
`mapWithIndex`
        (List
list List -> Getting (Seq Task) List (Seq Task) -> Seq Task
forall s a. s -> Getting a s a -> a
^. Getting (Seq Task) List (Seq Task)
Lens' List (Seq Task)
tasks)
    let widget :: Widget ResourceName
widget =
            (if Bool -> Bool
not Bool
eTitle
                 then ResourceName -> Widget ResourceName -> Widget ResourceName
forall n. Ord n => n -> Widget n -> Widget n
cached (Int -> ResourceName
RNList Int
listIndex)
                 else Widget ResourceName -> Widget ResourceName
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id) (Widget ResourceName -> Widget ResourceName)
-> ([Widget ResourceName] -> Widget ResourceName)
-> [Widget ResourceName]
-> Widget ResourceName
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
.
            Int -> Widget ResourceName -> Widget ResourceName
forall n. Int -> Widget n -> Widget n
padLeftRight (Config -> Int
columnPadding Config
layout) (Widget ResourceName -> Widget ResourceName)
-> ([Widget ResourceName] -> Widget ResourceName)
-> [Widget ResourceName]
-> Widget ResourceName
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
.
            Int -> Widget ResourceName -> Widget ResourceName
forall n. Int -> Widget n -> Widget n
hLimit (Config -> Int
columnWidth Config
layout) (Widget ResourceName -> Widget ResourceName)
-> ([Widget ResourceName] -> Widget ResourceName)
-> [Widget ResourceName]
-> Widget ResourceName
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
.
            ResourceName
-> ViewportType -> Widget ResourceName -> Widget ResourceName
forall n.
(Ord n, Show n) =>
n -> ViewportType -> Widget n -> Widget n
viewport (Int -> ResourceName
RNList Int
listIndex) ViewportType
Vertical (Widget ResourceName -> Widget ResourceName)
-> ([Widget ResourceName] -> Widget ResourceName)
-> [Widget ResourceName]
-> Widget ResourceName
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [Widget ResourceName] -> Widget ResourceName
forall n. [Widget n] -> Widget n
vBox ([Widget ResourceName] -> Widget ResourceName)
-> ([Widget ResourceName] -> [Widget ResourceName])
-> [Widget ResourceName]
-> Widget ResourceName
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Widget ResourceName
titleWidget Widget ResourceName
-> [Widget ResourceName] -> [Widget ResourceName]
forall a. a -> [a] -> [a]
:) ([Widget ResourceName] -> Widget ResourceName)
-> [Widget ResourceName] -> Widget ResourceName
forall a b. (a -> b) -> a -> b
$
            Seq (Widget ResourceName) -> [Element (Seq (Widget ResourceName))]
forall mono. MonoFoldable mono => mono -> [Element mono]
toList Seq (Widget ResourceName)
taskWidgets
    Widget ResourceName -> DSWidget
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Widget ResourceName -> DSWidget)
-> Widget ResourceName -> DSWidget
forall a b. (a -> b) -> a -> b
$
        if Int
currentList Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
listIndex
            then Widget ResourceName -> Widget ResourceName
forall n. Widget n -> Widget n
visible Widget ResourceName
widget
            else Widget ResourceName
widget