{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

module Cardano.RTView.GUI.Elements
    ( HTMLClass (..)
    , HTMLW3Class (..)
    , HTMLId (..)
    , NodesStateElements
    , NodeStateElements
    , ElementName (..)
    , ElementValue (..)
    , PeerInfoItem (..)
    , PeerInfoElements (..)
    , (<+>)
    , (##)
    , showIt
    , hideIt
    , showRow
    , showCell
    ) where

import           Cardano.Prelude hiding (unwords)
import           Control.DeepSeq (NFData (..), rwhnf)
import           Data.Map.Strict (Map)
import           Prelude (Show (..), String, unwords)

import qualified Graphics.UI.Threepenny as UI
import           Graphics.UI.Threepenny.Core (Element, UI, ( # ))

instance NFData Element where
  rnf :: Element -> ()
rnf = Element -> ()
forall a. a -> ()
rwhnf

-- | GUI elements containing current node state (info, metrics).
--   These elements are continuously updating using |LogObject|s
--   received by |TraceAcceptor|s.
type NodeStateElements = Map ElementName Element

-- | GUI elements for all nodes, tuples from nodeName, its elements and prepared peers items.
type NodesStateElements = [(Text, NodeStateElements, [PeerInfoItem])]

data ElementName
  = ElNodeProtocol
  | ElNodeVersion
  | ElNodePlatform
  | ElNodeCommitHref
  | ElActiveNode
  | ElUptime
  | ElEpoch
  | ElSlot
  | ElBlocksNumber
  | ElBlocksForgedNumber
  | ElNodeCannotForge
  | ElChainDensity
  | ElNodeIsLeaderNumber
  | ElSlotsMissedNumber
  | ElTxsProcessed
  | ElPeersNumber
  | ElTraceAcceptorHost
  | ElTraceAcceptorPort
  | ElTraceAcceptorEndpoint
  | ElOpCertStartKESPeriod
  | ElCurrentKESPeriod
  | ElRemainingKESPeriods
  | ElNodeErrors
  | ElNodeErrorsTab
  | ElMempoolTxsNumber
  | ElMempoolTxsPercent
  | ElMempoolBytes
  | ElMempoolBytesPercent
  | ElMempoolMaxTxs
  | ElMempoolMaxBytes
  | ElMemory
  | ElMemoryMax
  | ElMemoryMaxTotal
  | ElMemoryPercent
  | ElCPUPercent
  | ElCPULast
  | ElCPUNs
  | ElDiskUsageR
  | ElDiskUsageRMax
  | ElDiskUsageRMaxTotal
  | ElDiskUsageRPercent
  | ElDiskUsageW
  | ElDiskUsageWMax
  | ElDiskUsageWMaxTotal
  | ElDiskUsageWPercent
  | ElNetworkUsageIn
  | ElNetworkUsageInMaxTotal
  | ElNetworkUsageOut
  | ElNetworkUsageOutMaxTotal
  | ElRTSMemoryAllocated
  | ElRTSMemoryUsed
  | ElRTSMemoryUsedPercent
  | ElRTSGcCpu
  | ElRTSGcElapsed
  | ElRTSGcNum
  | ElRTSGcMajorNum
  -- Progress bars.
  | ElMempoolBytesProgress
  | ElMempoolBytesProgressBox
  | ElMempoolTxsProgress
  | ElMempoolTxsProgressBox
  | ElRTSMemoryProgress
  | ElRTSMemoryProgressBox
  -- Charts
  | ElMemoryUsageChart
  | ElCPUUsageChart
  | ElDiskUsageChart
  | ElNetworkUsageChart
  deriving (ElementName -> ElementName -> Bool
(ElementName -> ElementName -> Bool)
-> (ElementName -> ElementName -> Bool) -> Eq ElementName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ElementName -> ElementName -> Bool
$c/= :: ElementName -> ElementName -> Bool
== :: ElementName -> ElementName -> Bool
$c== :: ElementName -> ElementName -> Bool
Eq, (forall x. ElementName -> Rep ElementName x)
-> (forall x. Rep ElementName x -> ElementName)
-> Generic ElementName
forall x. Rep ElementName x -> ElementName
forall x. ElementName -> Rep ElementName x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ElementName x -> ElementName
$cfrom :: forall x. ElementName -> Rep ElementName x
Generic, ElementName -> ()
(ElementName -> ()) -> NFData ElementName
forall a. (a -> ()) -> NFData a
rnf :: ElementName -> ()
$crnf :: ElementName -> ()
NFData, Eq ElementName
Eq ElementName
-> (ElementName -> ElementName -> Ordering)
-> (ElementName -> ElementName -> Bool)
-> (ElementName -> ElementName -> Bool)
-> (ElementName -> ElementName -> Bool)
-> (ElementName -> ElementName -> Bool)
-> (ElementName -> ElementName -> ElementName)
-> (ElementName -> ElementName -> ElementName)
-> Ord ElementName
ElementName -> ElementName -> Bool
ElementName -> ElementName -> Ordering
ElementName -> ElementName -> ElementName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ElementName -> ElementName -> ElementName
$cmin :: ElementName -> ElementName -> ElementName
max :: ElementName -> ElementName -> ElementName
$cmax :: ElementName -> ElementName -> ElementName
>= :: ElementName -> ElementName -> Bool
$c>= :: ElementName -> ElementName -> Bool
> :: ElementName -> ElementName -> Bool
$c> :: ElementName -> ElementName -> Bool
<= :: ElementName -> ElementName -> Bool
$c<= :: ElementName -> ElementName -> Bool
< :: ElementName -> ElementName -> Bool
$c< :: ElementName -> ElementName -> Bool
compare :: ElementName -> ElementName -> Ordering
$ccompare :: ElementName -> ElementName -> Ordering
$cp1Ord :: Eq ElementName
Ord, Int -> ElementName -> ShowS
[ElementName] -> ShowS
ElementName -> String
(Int -> ElementName -> ShowS)
-> (ElementName -> String)
-> ([ElementName] -> ShowS)
-> Show ElementName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ElementName] -> ShowS
$cshowList :: [ElementName] -> ShowS
show :: ElementName -> String
$cshow :: ElementName -> String
showsPrec :: Int -> ElementName -> ShowS
$cshowsPrec :: Int -> ElementName -> ShowS
Show)

data ElementValue
  = ElementInt     !Int
  | ElementInteger !Integer
  | ElementWord64  !Word64
  | ElementDouble  !Double
  | ElementString  !String
  deriving ((forall x. ElementValue -> Rep ElementValue x)
-> (forall x. Rep ElementValue x -> ElementValue)
-> Generic ElementValue
forall x. Rep ElementValue x -> ElementValue
forall x. ElementValue -> Rep ElementValue x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ElementValue x -> ElementValue
$cfrom :: forall x. ElementValue -> Rep ElementValue x
Generic, ElementValue -> ()
(ElementValue -> ()) -> NFData ElementValue
forall a. (a -> ()) -> NFData a
rnf :: ElementValue -> ()
$crnf :: ElementValue -> ()
NFData)

-- | An item for each connected peer, contains a parent element
--   and list of child elements.
data PeerInfoItem
  = PeerInfoItem
      { PeerInfoItem -> Element
piItem      :: !Element
      , PeerInfoItem -> PeerInfoElements
piItemElems :: !PeerInfoElements
      }
  deriving ((forall x. PeerInfoItem -> Rep PeerInfoItem x)
-> (forall x. Rep PeerInfoItem x -> PeerInfoItem)
-> Generic PeerInfoItem
forall x. Rep PeerInfoItem x -> PeerInfoItem
forall x. PeerInfoItem -> Rep PeerInfoItem x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PeerInfoItem x -> PeerInfoItem
$cfrom :: forall x. PeerInfoItem -> Rep PeerInfoItem x
Generic, PeerInfoItem -> ()
(PeerInfoItem -> ()) -> NFData PeerInfoItem
forall a. (a -> ()) -> NFData a
rnf :: PeerInfoItem -> ()
$crnf :: PeerInfoItem -> ()
NFData)

data PeerInfoElements
  = PeerInfoElements
      { PeerInfoElements -> Element
pieEndpoint   :: !Element
      , PeerInfoElements -> Element
pieBytesInF   :: !Element
      , PeerInfoElements -> Element
pieReqsInF    :: !Element
      , PeerInfoElements -> Element
pieBlocksInF  :: !Element
      , PeerInfoElements -> Element
pieSlotNumber :: !Element
      , PeerInfoElements -> Element
pieStatus     :: !Element
      }
  deriving ((forall x. PeerInfoElements -> Rep PeerInfoElements x)
-> (forall x. Rep PeerInfoElements x -> PeerInfoElements)
-> Generic PeerInfoElements
forall x. Rep PeerInfoElements x -> PeerInfoElements
forall x. PeerInfoElements -> Rep PeerInfoElements x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PeerInfoElements x -> PeerInfoElements
$cfrom :: forall x. PeerInfoElements -> Rep PeerInfoElements x
Generic, PeerInfoElements -> ()
(PeerInfoElements -> ()) -> NFData PeerInfoElements
forall a. (a -> ()) -> NFData a
rnf :: PeerInfoElements -> ()
$crnf :: PeerInfoElements -> ()
NFData)

-- | HTML elements identifiers, we use them in HTML, CSS and JS FFI.

data HTMLClass
  = ActiveTab
  | BarValueUnit
  | 
  | CommitLink
  | DensityPercent
  | ErrorsTabContainer
  | GridNodeNameLabel
  | GridRowCell
  | HSpacer
  | InfoMark
  | InfoMarkImg
  | MetricsArea
  | NodeContainer
  | NodeBar
  | NodeInfoValues
  | NodeInfoVSpacer
  | NodeMetricsValues
  | NodeMetricsVSpacer
  | NodeMenuIcon
  | NodeName
  | NodeNameArea
  | OutdatedValue
  | PercentsSlashHSpacer
  | PercentsSlashHRSpacer
  | ProgressBar
  | ProgressBarOutdated
  | ProgressBarBox
  | ProgressBarBoxOutdated
  | ReleaseName
  | ResourcesIcon
  | SelectMetricCheck
  | SelectMetricCheckArea
  | SelectNodeCheck
  | SelectNodeCheckArea
  | ServiceName
  | ShowHideIcon
  | TabContainer
  | TopBar
  | ValueUnit
  | ValueUnitPercent
  -- Charts
  | CPUUsageChart
  | MemoryUsageChart
  | DiskUsageChart
  | NetworkUsageChart
  | GridCPUUsageChart
  | GridMemoryUsageChart
  | GridDiskUsageChart
  | GridNetworkUsageChart
  -- Error messages
  | WarningMessage
  | ErrorMessage
  | CriticalMessage
  | AlertMessage
  | EmergencyMessage
  deriving Int -> HTMLClass -> ShowS
[HTMLClass] -> ShowS
HTMLClass -> String
(Int -> HTMLClass -> ShowS)
-> (HTMLClass -> String)
-> ([HTMLClass] -> ShowS)
-> Show HTMLClass
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HTMLClass] -> ShowS
$cshowList :: [HTMLClass] -> ShowS
show :: HTMLClass -> String
$cshow :: HTMLClass -> String
showsPrec :: Int -> HTMLClass -> ShowS
$cshowsPrec :: Int -> HTMLClass -> ShowS
Show

data HTMLW3Class
  = W3Bar
  | W3BarBlock
  | W3BarItem
  | W3Border
  | W3Bordered
  | W3BorderBottom
  | W3BorderTop
  | W3Button
  | W3Card4
  | W3Check
  | W3Col
  | W3Container
  | W3Disabled
  | W3DropdownContent
  | W3DropdownHover
  | W3Half
  | W3HideMedium
  | W3HideSmall
  | W3Large
  | W3Margin
  | W3Mobile
  | W3Responsive
  | W3Rest
  | W3Right
  | W3RightAlign
  | W3Row
  | W3Sidebar
  | W3Table
  | W3Theme
  | W3Third
  | W3TwoThird
  | W3Quarter
  | W3L6
  | W3M12
  | W3S12

-- | We have to provide explicit Show-instance,
--   because all these classes are taken from W3C-library.
instance Show HTMLW3Class where
  show :: HTMLW3Class -> String
show HTMLW3Class
W3Bar             = String
"w3-bar"
  show HTMLW3Class
W3BarBlock        = String
"w3-bar-block"
  show HTMLW3Class
W3BarItem         = String
"w3-bar-item"
  show HTMLW3Class
W3Border          = String
"w3-border"
  show HTMLW3Class
W3Bordered        = String
"w3-bordered"
  show HTMLW3Class
W3BorderBottom    = String
"w3-border-bottom"
  show HTMLW3Class
W3BorderTop       = String
"w3-border-top"
  show HTMLW3Class
W3Button          = String
"w3-button"
  show HTMLW3Class
W3Card4           = String
"w3-card-4"
  show HTMLW3Class
W3Check           = String
"w3-check"
  show HTMLW3Class
W3Col             = String
"w3-col"
  show HTMLW3Class
W3Container       = String
"w3-container"
  show HTMLW3Class
W3Disabled        = String
"w3-disabled"
  show HTMLW3Class
W3DropdownContent = String
"w3-dropdown-content"
  show HTMLW3Class
W3DropdownHover   = String
"w3-dropdown-hover"
  show HTMLW3Class
W3Half            = String
"w3-half"
  show HTMLW3Class
W3HideMedium      = String
"w3-hide-medium"
  show HTMLW3Class
W3HideSmall       = String
"w3-hide-small"
  show HTMLW3Class
W3Large           = String
"w3-large"
  show HTMLW3Class
W3Margin          = String
"w3-margin"
  show HTMLW3Class
W3Mobile          = String
"w3-mobile"
  show HTMLW3Class
W3Responsive      = String
"w3-responsive"
  show HTMLW3Class
W3Rest            = String
"w3-rest"
  show HTMLW3Class
W3Right           = String
"w3-right"
  show HTMLW3Class
W3RightAlign      = String
"w3-right-align"
  show HTMLW3Class
W3Row             = String
"w3-row"
  show HTMLW3Class
W3Sidebar         = String
"w3-sidebar"
  show HTMLW3Class
W3Table           = String
"w3-table"
  show HTMLW3Class
W3Theme           = String
"w3-theme"
  show HTMLW3Class
W3Third           = String
"w3-third"
  show HTMLW3Class
W3TwoThird        = String
"w3-twothird"
  show HTMLW3Class
W3Quarter         = String
"w3-quarter"
  show HTMLW3Class
W3L6              = String
"l6"
  show HTMLW3Class
W3M12             = String
"m12"
  show HTMLW3Class
W3S12             = String
"s12"

-- | Operator for class names concatenation. Please note
--   that w3-classes should be the first, because our
--   own classes override some of them.
(<+>) :: [HTMLW3Class] -> [HTMLClass] -> String
<+> :: [HTMLW3Class] -> [HTMLClass] -> String
(<+>) [HTMLW3Class]
w3Classes [HTMLClass]
ownClasses = [String] -> String
unwords [String]
allClasses
 where
  allClasses :: [String]
allClasses = (HTMLW3Class -> String) -> [HTMLW3Class] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map HTMLW3Class -> String
forall a. Show a => a -> String
Prelude.show [HTMLW3Class]
w3Classes [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (HTMLClass -> String) -> [HTMLClass] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map HTMLClass -> String
forall a. Show a => a -> String
Prelude.show [HTMLClass]
ownClasses

data HTMLId
  = SelectMetricButton
  | HideAllMetricsButton
  | ShowAllMetricsButton
  | HideAllNodesButton
  | ShowAllNodesButton
  | ViewModeButton
  -- Id parts (the final id will be formed using unique name of node).
  | CPUUsageChartId
  | DiskUsageChartId
  | MemoryUsageChartId
  | NetworkUsageChartId
  | GridCPUUsageChartId
  | GridDiskUsageChartId
  | GridMemoryUsageChartId
  | GridNetworkUsageChartId
  | GridNodeTH
  deriving Int -> HTMLId -> ShowS
[HTMLId] -> ShowS
HTMLId -> String
(Int -> HTMLId -> ShowS)
-> (HTMLId -> String) -> ([HTMLId] -> ShowS) -> Show HTMLId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HTMLId] -> ShowS
$cshowList :: [HTMLId] -> ShowS
show :: HTMLId -> String
$cshow :: HTMLId -> String
showsPrec :: Int -> HTMLId -> ShowS
$cshowsPrec :: Int -> HTMLId -> ShowS
Show

(##) :: UI Element -> String  -> UI Element
## :: UI Element -> String -> UI Element
(##) UI Element
el String
i = UI Element
el UI Element -> (UI Element -> UI Element) -> UI Element
forall a b. a -> (a -> b) -> b
# ReadWriteAttr Element String ()
-> String -> UI Element -> UI Element
forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
UI.set ReadWriteAttr Element String ()
UI.id_ String
i

showIt, hideIt, showRow, showCell :: UI Element -> UI Element
showIt :: UI Element -> UI Element
showIt   = ReadWriteAttr Element [(String, String)] ()
-> [(String, String)] -> UI Element -> UI Element
forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
UI.set ReadWriteAttr Element [(String, String)] ()
UI.style [(String
"display", String
"block")]
hideIt :: UI Element -> UI Element
hideIt   = ReadWriteAttr Element [(String, String)] ()
-> [(String, String)] -> UI Element -> UI Element
forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
UI.set ReadWriteAttr Element [(String, String)] ()
UI.style [(String
"display", String
"none")]
showRow :: UI Element -> UI Element
showRow  = ReadWriteAttr Element [(String, String)] ()
-> [(String, String)] -> UI Element -> UI Element
forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
UI.set ReadWriteAttr Element [(String, String)] ()
UI.style [(String
"display", String
"table-row")]
showCell :: UI Element -> UI Element
showCell = ReadWriteAttr Element [(String, String)] ()
-> [(String, String)] -> UI Element -> UI Element
forall x i o. ReadWriteAttr x i o -> i -> UI x -> UI x
UI.set ReadWriteAttr Element [(String, String)] ()
UI.style [(String
"display", String
"table-cell")]