module Gargantext.Components.Search.SearchField
  ( Search, Props, searchField, searchFieldComponent )where

import Prelude hiding (div)
import Data.Map as Map
import Data.Maybe ( Maybe(..), maybe, maybe' )
import Data.Nullable (Nullable, null)
import Data.Traversable ( traverse_ )
import Data.Tuple ( Tuple(..), fst )
import Data.Tuple.Nested ( (/\) )
import DOM.Simple as DOM
import DOM.Simple.Console
import DOM.Simple.Element as Element
import DOM.Simple.Event as DE
import Effect ( Effect )
import Effect.Uncurried (mkEffectFn1)
import FFI.Simple ((..))
import Reactix as R
import Reactix.DOM.HTML as HTML
import Reactix.DOM.HTML (text, button, div, input, option, form, span, ul, li, a)
import Reactix.SyntheticEvent as E
import Gargantext.Components.Search.Types

select = R.createElement "select"

type Search = { database :: Maybe Database, term :: String }

defaultSearch :: Search
defaultSearch = { database: Nothing, term: "" }

type Props =
  -- list of databases to search, or parsers to use on uploads
  ( databases :: Array Database
  -- State hook for a search, how we get data in and out
  , search :: R.State (Maybe Search)
  )

searchField :: Record Props -> R.Element
searchField p = R.createElement searchFieldComponent p []

placeholder :: String
placeholder = "Query, URL or FILE (works with Firefox or Chromium browsers)"

searchFieldComponent :: R.Memo Props
searchFieldComponent = R.memo (R.hooksComponent "SearchField" cpt) hasChanged
  where
    cpt props _ = do
      let search = maybe defaultSearch identity (fst props.search)
      term <- R.useState' search.term
      db   <- R.useState' (Nothing :: Maybe Database)
      pure $
          div { className: "search-field input-group" }
              [ databaseInput db props.databases
              , searchInput term
              , span { className: "input-group-btn" }
                     [ submitButton db term props.search ]
              ]
    hasChanged p p' = (fst p.search /= fst p'.search) || (p.databases /= p'.databases)

databaseInput :: R.State (Maybe Database) -> Array Database -> R.Element
databaseInput (db /\ setDB) dbs =
  div { className: "input-group-btn search-panel dropdown" }
      [ dropdownBtn db
      , ul {className: "dropdown-menu", role: "menu"} (liItem <$> dbs)
      ]
  where
    liItem db = li { onClick } [ a {href: "#"} [text (show db) ] ]
      where
        onClick = mkEffectFn1 $ \_ -> setDB $ const $ Just db
    dropdownBtnProps = { id: "search-dropdown"
                        , className: "btn btn-default dropdown-toggle"
                        , type: "button"
                        , data: {toggle: "dropdown"}
                        }
    dropdownBtn (Just db) = button dropdownBtnProps [ span {} [ text (show db) ] ]
    dropdownBtn (Nothing) = button dropdownBtnProps [ span {} [ text "-" ] ]

searchInput :: R.State String -> R.Element
searchInput (term /\ setTerm) =
  input { defaultValue: term
        , className: "form-control"
        , type: "text"
        , onChange
        , placeholder }
  where onChange = mkEffectFn1 $ \e -> setTerm $ const $ e .. "target" .. "value"


submitButton :: R.State (Maybe Database) -> R.State String -> R.State (Maybe Search) -> R.Element
submitButton (database /\ _) (term /\ _) (_ /\ setSearch) =
  button { className: "btn btn-default", type: "button", onClick: click } [ text "Search" ]
  where
    click = mkEffectFn1 $ \_ -> do
      case term of
        "" -> setSearch $ const Nothing
        _  -> setSearch $ const $ Just { database, term }