{-# LANGUAGE RecordWildCards #-}
module Main where

import qualified Graphics.Vty              as V

import qualified Brick.AttrMap             as A
import qualified Brick.Main                as M
import           Brick.Types               (Widget)
import qualified Brick.Types               as T
import           Brick.Util                as B
import qualified Brick.Widgets.Border      as B
import qualified Brick.Widgets.Center      as C
import           Brick.Widgets.Core        (str, vBox, vLimit, withAttr)
import qualified Brick.Widgets.GroupedList as GL()
import qualified Brick.Widgets.List        as L
import qualified Data.Vector               as V

import           Core.Types                (ApplicationState (..),
                                            initializeApplicationState)
import qualified Git

drawUI :: ApplicationState -> [Widget]
drawUI (ApplicationStateConst {..}) = [ui]
    where
        stagedBox = fileListBox stagedFiles "Staged Files" position
        unStagedBox = fileListBox unstagedFiles "Unstaged Files" (position - V.length (L.listElements stagedFiles))
        helpBox = vBox $ fmap C.hCenter [str "Press ESC to exit"]
        ui = C.vCenter $ vBox [ C.vCenter stagedBox
                              , C.vCenter unStagedBox
                              , helpBox
                              ]
fileListBox :: L.List Git.File -> String -> Int -> Widget
fileListBox files label pos  = B.borderWithLabel (str label) $
                                vLimit 8 $
                                L.renderList files (drawFileListElement colorize)
  where colorize = pos > 0 && pos <= V.length (L.listElements files)

appEvent :: ApplicationState -> V.Event -> T.EventM (T.Next ApplicationState)
appEvent applicationState event =
    case event of
        V.EvKey V.KEsc [] -> M.halt applicationState

        _ -> T.handleEvent event applicationState >>= M.continue

drawFileListElement ::Bool -> Bool -> Git.File -> Widget
drawFileListElement isSelected1 isSelected2 (Git.File {name=name}) = C.hCenter $ addAttr realSelectedAttr $ str name
  where addAttr attr = if isSelected1 && isSelected2
                        then withAttr attr
                        else withAttr mempty


realSelectedAttr :: A.AttrName
realSelectedAttr = L.listSelectedAttr <> "custom"

theMap :: A.AttrMap
theMap = A.attrMap V.defAttr
    [ (L.listAttr <> L.listSelectedAttr, V.brightYellow `B.on` V.black)
    , (realSelectedAttr,                 V.black `B.on` V.brightYellow)
    ]

theApp :: M.App ApplicationState V.Event
theApp =
    M.App { M.appDraw = drawUI
          , M.appChooseCursor = M.neverShowCursor
          , M.appHandleEvent = appEvent
          , M.appStartEvent = return
          , M.appAttrMap = const theMap
          , M.appLiftVtyEvent = id
          }

main :: IO ()
main = do
  initialState <- initializeApplicationState
  void $ M.defaultMain theApp initialState
