module Gargantext.Components.Themes where

import Gargantext.Prelude

import Data.Array as A
import Data.Eq.Generic (genericEq)
import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..), maybe)
import Effect (Effect)
import FFI.Simple ((.=))
import Gargantext.Utils.Reactix (getElementById, (~~))
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T

here :: R2.Here
here = R2.here "Gargantext.Components.Themes"

stylesheetElId :: String
stylesheetElId = "bootstrap-css"

newtype Theme = Theme { location :: String
                      , name :: String }
derive instance Generic Theme _
instance Eq Theme where
  eq = genericEq

themeName :: Theme -> String
themeName (Theme { name }) = name

defaultTheme :: Theme
defaultTheme = Theme { name: "default"
                     , location: "styles/bootstrap-default.css" }

greysonTheme :: Theme
greysonTheme = Theme { name: "greyson"
                     , location: "styles/bootstrap-greyson.css" }

monotonyTheme :: Theme
monotonyTheme = Theme { name: "monotony"
                      , location: "styles/bootstrap-monotony.css" }

herbieTheme :: Theme
herbieTheme = Theme { name: "herbie"
                      , location: "styles/bootstrap-herbie.css" }

darksterTheme :: Theme
darksterTheme = Theme { name: "darkster"
                      , location: "styles/bootstrap-darkster.css" }

allThemes :: Array Theme
allThemes = [ defaultTheme, greysonTheme, monotonyTheme, herbieTheme, darksterTheme]

switchTheme :: Theme -> Effect Unit
switchTheme (Theme { location }) = do
  mEl <- R2.getElementById stylesheetElId
  case mEl of
    Nothing -> pure unit
    Just el -> do
      _ <- pure $ (el .= "href") location
      pure unit

markThemeToDOMTree :: Theme -> Effect Unit
markThemeToDOMTree (Theme { name }) = do
  let setTheme el = pure $ (el ~~ "setAttribute") [ "data-theme", name ]
  getElementById "app"    >>= maybe R.nothing (setTheme)
  getElementById "portal" >>= maybe R.nothing (setTheme)


type ThemeSwitcherProps = (
    theme  :: T.Box Theme
  , themes :: Array Theme
  )

themeSwitcher :: R2.Component ThemeSwitcherProps
themeSwitcher = R.createElement themeSwitcherCpt
themeSwitcherCpt :: R.Component ThemeSwitcherProps
themeSwitcherCpt = here.component "themeSwitcher" cpt where
  cpt { theme, themes } _ = do
    currentTheme <- T.useLive T.unequal theme

    let option (Theme { name }) = H.option { value: name } [ H.text name ]
    let options = map option themes

    R.useEffectOnce' $ markThemeToDOMTree currentTheme

    pure $ R2.select { className: "form-control rounded-circle-2"
                     , defaultValue: themeName currentTheme
                     , on: { change: onChange theme } } options
    where
      onChange box e = do
        let value = R.unsafeEventValue e
        let mTheme = A.head $ A.filter (\(Theme { name }) -> value == name) themes

        case mTheme of
          Nothing -> pure unit
          Just t  -> do
            switchTheme t
            markThemeToDOMTree t
            T.write_ t box