module Gargantext.Components.GraphExplorer.Sidebar.Legend
  ( Props, legend
  ) where

import Prelude hiding (map)

import Data.Array as A
import Data.Maybe (isJust, maybe)
import Data.Sequence (Seq)
import Data.Set as Set
import Data.Traversable (foldMap, intercalate)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.GraphExplorer.GraphTypes as GEGT
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Hooks.Sigmax.Types as ST
import Gargantext.Utils (getter, nbsp, (?))
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.GraphExplorer.Sidebar.Legend"

type Props =
  ( legendSeq             :: Seq GET.Legend
  , extractedNodeList     :: Array GEGT.Node
  , nodeCountList         :: Array GEGT.ClusterCount
  , selectedNodeIds       :: T.Box ST.NodeIds
  )

legend :: R2.Leaf Props
legend = R2.leaf legendCpt
legendCpt :: R.Component Props
legendCpt = here.component "legend" cpt where
  cpt { legendSeq
      , extractedNodeList
      , nodeCountList
      , selectedNodeIds
      } _ = do
    -- | Hooks
    -- |
    R.useEffectOnce' $ here.info2 "legend" extractedNodeList
    -- | Render
    -- |
    pure $

      H.ul
      { className: "graph-legend" }
      [
        flip foldMap legendSeq \(GET.Legend { id_, label }) ->

          H.li
          { className: "graph-legend__item" }
          [
            H.div
            { className: "graph-legend__code"
            , style: { backgroundColor: GET.intColor id_ }
            }
            []
          ,
            B.wad
            [ "flex-grow-1" ]
            [
              B.div'
              { className: "graph-legend__title" }
              label
            ,
              selectedNodes
              { selectedNodeIds
              , extractedNodeList
              , clusterId: id_
              , nodeCount: getClusterNodeCount nodeCountList id_
              }
            ]
          ]
      ]

filterByCluster :: Int -> Array GEGT.Node -> Array GEGT.Node
filterByCluster id
  =   A.filter
      (   getter _.attributes
      >>> getter _.clustDefault
      >>> eq id
      )

getClusterNodeCount :: Array GEGT.ClusterCount -> Int -> Int
getClusterNodeCount nodeCountList id
  =   nodeCountList
  #   A.find
      (   getter _.id
      >>> eq id
      )
  >>> maybe 0
      (   getter _.count
      )

---------------------------------------------------------

type SelectedNodesProps =
  ( extractedNodeList     :: Array GEGT.Node
  , selectedNodeIds       :: T.Box ST.NodeIds
  , clusterId             :: Int
  , nodeCount             :: Int
  )

selectedNodes :: R2.Leaf SelectedNodesProps
selectedNodes = R2.leaf selectedNodesCpt

selectedNodesCpt :: R.Component SelectedNodesProps
selectedNodesCpt = here.component "selectedNodes" cpt where
  cpt { extractedNodeList
      , selectedNodeIds
      , clusterId
      , nodeCount
      } _ = do
    -- | States
    -- |
    selectedNodeIds' <- R2.useLive' selectedNodeIds
    -- | Computed
    -- |
    let
      isSelected id
        =   selectedNodeIds'
        # A.fromFoldable
        # A.find
            ( eq id
            )
        # isJust

      countValue
        =   extractedNodeList
        #   A.length
        #   (nodeCount - _)

    -- | Behaviors
    -- |
    let
      onBadgeClick id _ = T.write_ (Set.singleton id) selectedNodeIds

    -- | Render
    -- |
    pure $

      H.ul
      { className: "graph-legend-nodes" }
      [
        flip foldMap (filterByCluster clusterId extractedNodeList)
        \(GEGT.Node { label: nodeLabel, id_: nodeId }) ->

          H.li
          { className: "graph-legend-nodes__item" }
          [
            H.a
            { className: intercalate " "
                [ "graph-legend-nodes__badge"
                , (isSelected nodeId) ?
                    "graph-legend-nodes__badge--selected" $
                    ""
                , "badge badge-light"
                ]
            , on: { click: onBadgeClick nodeId }
            }
            [ H.text nodeLabel ]
          ]

      ,
        R2.when (eq countValue 0) $

          H.li
          { className: intercalate " "
              [ "graph-legend-nodes__item"
              , "graph-legend-nodes__item--count"
              ]
          }
          [
            H.text "0 node"
          ]
      ,
        R2.when (not $ eq countValue 0) $

          H.li
          { className: intercalate " "
              [ "graph-legend-nodes__item"
              , "graph-legend-nodes__item--count"
              ]
          }
          [
            H.text "+"
          ,
            H.text $ nbsp 1
          ,
            H.text $ show countValue
          ,
            H.text $ nbsp 1
          ,
            H.text $ eq countValue 1 ? "node" $ "nodes"
          ]
      ]