content: {-# LANGUAGE MultiWayIf #-}
  {-# LANGUAGE TupleSections #-}
  {-# LANGUAGE OverloadedStrings #-}
  module App
    ( application
    , mkInitialState
    )
  where
  
  import Control.Monad.Trans (liftIO)
  import qualified Graphics.Vty as V
  import qualified Data.Vector as Vec
  import qualified Data.Map as M
  import Lens.Micro.Platform
  import qualified Data.Text as T
  
  import Brick
  import Brick.BChan (BChan)
  import Brick.Focus
  import Brick.Widgets.Edit (editor)
  
  import Types
  import Events
  import UI
  import Theme
  import Tart.Canvas
  
  defaultPalette :: Vec.Vector (Maybe V.Color)
  defaultPalette = Vec.fromList
      [ Nothing -- default attribute
      , Just V.white
      , Just V.brightWhite
      , Just V.black
      , Just V.brightBlack
      , Just V.blue
      , Just V.brightBlue
      , Just V.red
      , Just V.brightRed
      , Just V.magenta
      , Just V.brightMagenta
      , Just V.green
      , Just V.brightGreen
      , Just V.cyan
      , Just V.brightCyan
      , Just V.yellow
      , Just V.brightYellow
      ]
  
  initialCanvasSize :: (Int, Int)
  initialCanvasSize = (40, 17)
  
  mkInitialState :: BChan AppEvent
                 -> Maybe (Maybe FilePath, [Canvas], [Int], [T.Text])
                 -> IO AppState
  mkInitialState chan mc = do
      (cs, order, names, fp) <- case mc of
          Nothing -> do
              c <- newCanvas initialCanvasSize
              return ([c], [0], [T.pack "default"], Nothing)
          Just (fp, cs, order, names) ->
              return (cs, order, names, fp)
  
      let sz = canvasSize $ cs !! 0
      overlay <- newCanvas sz
  
      return $ AppState { _layers                  = M.fromList $ zip [0..] cs
                        , _layerInfo               = M.fromList $ zip [0..] (LayerInfo <$> names <*> pure True)
                        , _layerOrder              = order
                        , _drawingOverlay          = overlay
                        , _layerListVisible        = True
                        , _selectedLayerIndex      = head order
                        , _modes                   = [Main]
                        , _tool                    = Freehand
                        , _appCanvasSize           = sz
                        , _drawCharacter           = '*'
                        , _drawFgPaletteIndex      = 0
                        , _drawBgPaletteIndex      = 0
                        , _palette                 = defaultPalette
                        , _fgPaletteSelectorExtent = Nothing
                        , _bgPaletteSelectorExtent = Nothing
                        , _toolSelectorExtent      = Nothing
                        , _boxStyleSelectorExtent  = Nothing
                        , _styleSelectorExtent     = Nothing
                        , _canvasExtent            = Nothing
                        , _dragging                = Nothing
                        , _layerNameEditor         = editor LayerNameEditor (Just 1) ""
                        , _canvasSizeWidthEdit     = editor CanvasSizeWidthEdit (Just 1) ""
                        , _canvasSizeHeightEdit    = editor CanvasSizeHeightEdit (Just 1) ""
                        , _canvasSizeFocus         = focusRing [ CanvasSizeWidthEdit
                                                               , CanvasSizeHeightEdit
                                                               ]
                        , _canvasOffset            = Location $ sz & each %~ (`div` 2)
                        , _canvasPath              = fp
                        , _canvasDirty             = False
                        , _askToSaveFilenameEdit   = editor AskToSaveFilenameEdit (Just 1) ""
                        , _saveError               = Nothing
                        , _appEventChannel         = chan
                        , _textEntered             = mempty
                        , _textEntryStart          = (0, 0)
                        , _boxStyleIndex           = 0
                        , _eraserSize              = 1
                        , _repaintSize             = 1
                        , _restyleSize             = 1
                        , _undoStack               = []
                        , _redoStack               = []
                        , _drawStyle               = noStyle
                        }
  
  application :: App AppState AppEvent Name
  application =
      App { appDraw = drawUI
          , appChooseCursor = \s locs ->
              let isSaving = any isSavingMode
                  isSavingMode (AskForSaveFilename _) = True
                  isSavingMode _ = False
              in if | CanvasSizePrompt `elem` s^.modes -> do
                        cur <- focusGetCurrent (s^.canvasSizeFocus)
                        showCursorNamed cur locs
                    | isSaving (s^.modes) ->
                        showCursorNamed AskToSaveFilenameEdit locs
                    | TextEntry `elem` s^.modes ->
                        showCursorNamed TextEntryCursor locs
                    | RenameLayer `elem` s^.modes ->
                        showCursorNamed LayerNameEditor locs
                    | otherwise -> Nothing
          , appHandleEvent = handleEvent
          , appStartEvent = do
              vty <- getVtyHandle
              liftIO $ V.setMode (V.outputIface vty) V.Mouse True
              liftIO $ V.setMode (V.outputIface vty) V.BracketedPaste True
          , appAttrMap = const theme
          }
  