{-# LANGUAGE MultiParamTypeClasses #-}

-- |
-- Module     : Simulation.Aivika.Experiment.Base.ExperimentSpecsView
-- Copyright  : Copyright (c) 2012-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 8.0.1
--
-- The module defines 'ExperimentSpecsView' that shows the 
-- experiment specs.
--

module Simulation.Aivika.Experiment.Base.ExperimentSpecsView 
       (ExperimentSpecsView(..),
        defaultExperimentSpecsView) where

import Control.Monad
import Control.Monad.Trans

import Data.Monoid

import Simulation.Aivika.Experiment.Types
import Simulation.Aivika.Experiment.Base.WebPageRenderer
import Simulation.Aivika.Experiment.Base.HtmlWriter
import Simulation.Aivika.Experiment.Base.ExperimentWriter
import Simulation.Aivika.Experiment.Base.ExperimentSpecsWriter

-- | Defines the 'View' that shows the experiment specs.
data ExperimentSpecsView =
  ExperimentSpecsView { ExperimentSpecsView -> String
experimentSpecsTitle       :: String,
                        -- ^ The title for the view.
                        ExperimentSpecsView -> String
experimentSpecsDescription :: String,
                        -- ^ The description for the view.
                        ExperimentSpecsView -> ExperimentSpecsWriter
experimentSpecsWriter      :: ExperimentSpecsWriter
                        -- ^ It shows the specs.
                      }
  
-- | This is the default view.
defaultExperimentSpecsView :: ExperimentSpecsView
defaultExperimentSpecsView :: ExperimentSpecsView
defaultExperimentSpecsView =  
  ExperimentSpecsView :: String -> String -> ExperimentSpecsWriter -> ExperimentSpecsView
ExperimentSpecsView { experimentSpecsTitle :: String
experimentSpecsTitle       = String
"Experiment Specs",
                        experimentSpecsDescription :: String
experimentSpecsDescription = String
"It shows the experiment specs.",
                        experimentSpecsWriter :: ExperimentSpecsWriter
experimentSpecsWriter      = ExperimentSpecsWriter
defaultExperimentSpecsWriter }

instance ExperimentView ExperimentSpecsView (WebPageRenderer a) where  
  
  outputView :: ExperimentSpecsView -> ExperimentGenerator (WebPageRenderer a)
outputView ExperimentSpecsView
v = 
    let reporter :: Experiment
-> p
-> p
-> ExperimentWriter (ExperimentReporter (WebPageRenderer a))
reporter Experiment
exp p
renderer p
dir =
          do ExperimentSpecsViewState
st <- ExperimentSpecsView
-> Experiment -> ExperimentWriter ExperimentSpecsViewState
newExperimentSpecs ExperimentSpecsView
v Experiment
exp
             let context :: ExperimentContext (WebPageRenderer a)
context =
                   WebPageWriter -> ExperimentContext (WebPageRenderer a)
forall a. WebPageWriter -> ExperimentContext (WebPageRenderer a)
WebPageContext (WebPageWriter -> ExperimentContext (WebPageRenderer a))
-> WebPageWriter -> ExperimentContext (WebPageRenderer a)
forall a b. (a -> b) -> a -> b
$
                   WebPageWriter :: (Int -> HtmlWriter ()) -> (Int -> HtmlWriter ()) -> WebPageWriter
WebPageWriter { reporterWriteTOCHtml :: Int -> HtmlWriter ()
reporterWriteTOCHtml = ExperimentSpecsViewState -> Int -> HtmlWriter ()
experimentSpecsTOCHtml ExperimentSpecsViewState
st,
                                   reporterWriteHtml :: Int -> HtmlWriter ()
reporterWriteHtml    = ExperimentSpecsViewState -> Int -> HtmlWriter ()
experimentSpecsHtml ExperimentSpecsViewState
st }
             ExperimentReporter (WebPageRenderer a)
-> ExperimentWriter (ExperimentReporter (WebPageRenderer a))
forall (m :: * -> *) a. Monad m => a -> m a
return ExperimentReporter :: forall r.
ExperimentMonad r ()
-> ExperimentMonad r ()
-> (ExperimentData -> Composite ())
-> ExperimentContext r
-> ExperimentReporter r
ExperimentReporter { reporterInitialise :: ExperimentMonad (WebPageRenderer a) ()
reporterInitialise = () -> ExperimentWriter ()
forall (m :: * -> *) a. Monad m => a -> m a
return (),
                                         reporterFinalise :: ExperimentMonad (WebPageRenderer a) ()
reporterFinalise   = () -> ExperimentWriter ()
forall (m :: * -> *) a. Monad m => a -> m a
return (),
                                         reporterSimulate :: ExperimentData -> Composite ()
reporterSimulate   = Composite () -> ExperimentData -> Composite ()
forall a b. a -> b -> a
const (Composite () -> ExperimentData -> Composite ())
-> Composite () -> ExperimentData -> Composite ()
forall a b. (a -> b) -> a -> b
$ () -> Composite ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
forall a. Monoid a => a
mempty,
                                         reporterContext :: ExperimentContext (WebPageRenderer a)
reporterContext    = ExperimentContext (WebPageRenderer a)
forall a. ExperimentContext (WebPageRenderer a)
context }
    in ExperimentGenerator :: forall r.
(Experiment
 -> r
 -> ExperimentEnvironment r
 -> ExperimentMonad r (ExperimentReporter r))
-> ExperimentGenerator r
ExperimentGenerator { generateReporter :: Experiment
-> WebPageRenderer a
-> ExperimentEnvironment (WebPageRenderer a)
-> ExperimentMonad
     (WebPageRenderer a) (ExperimentReporter (WebPageRenderer a))
generateReporter = Experiment
-> WebPageRenderer a
-> ExperimentEnvironment (WebPageRenderer a)
-> ExperimentMonad
     (WebPageRenderer a) (ExperimentReporter (WebPageRenderer a))
forall p p a.
Experiment
-> p
-> p
-> ExperimentWriter (ExperimentReporter (WebPageRenderer a))
reporter }
  
-- | The state of the view.
data ExperimentSpecsViewState =
  ExperimentSpecsViewState { ExperimentSpecsViewState -> ExperimentSpecsView
experimentSpecsView       :: ExperimentSpecsView,
                             ExperimentSpecsViewState -> Experiment
experimentSpecsExperiment :: Experiment }
  
-- | Create a new state of the view.
newExperimentSpecs :: ExperimentSpecsView -> Experiment -> ExperimentWriter ExperimentSpecsViewState
newExperimentSpecs :: ExperimentSpecsView
-> Experiment -> ExperimentWriter ExperimentSpecsViewState
newExperimentSpecs ExperimentSpecsView
view Experiment
exp =
  ExperimentSpecsViewState
-> ExperimentWriter ExperimentSpecsViewState
forall (m :: * -> *) a. Monad m => a -> m a
return ExperimentSpecsViewState :: ExperimentSpecsView -> Experiment -> ExperimentSpecsViewState
ExperimentSpecsViewState { experimentSpecsView :: ExperimentSpecsView
experimentSpecsView       = ExperimentSpecsView
view,
                                    experimentSpecsExperiment :: Experiment
experimentSpecsExperiment = Experiment
exp }
       
-- | Get the HTML code.     
experimentSpecsHtml :: ExperimentSpecsViewState -> Int -> HtmlWriter ()     
experimentSpecsHtml :: ExperimentSpecsViewState -> Int -> HtmlWriter ()
experimentSpecsHtml ExperimentSpecsViewState
st Int
index =
  do ExperimentSpecsViewState -> Int -> HtmlWriter ()
header ExperimentSpecsViewState
st Int
index
     let writer :: ExperimentSpecsWriter
writer = ExperimentSpecsView -> ExperimentSpecsWriter
experimentSpecsWriter (ExperimentSpecsViewState -> ExperimentSpecsView
experimentSpecsView ExperimentSpecsViewState
st)
         write :: ExperimentSpecsWriter -> Experiment -> HtmlWriter ()
write  = ExperimentSpecsWriter
-> ExperimentSpecsWriter -> Experiment -> HtmlWriter ()
experimentSpecsWrite ExperimentSpecsWriter
writer
         exp :: Experiment
exp    = ExperimentSpecsViewState -> Experiment
experimentSpecsExperiment ExperimentSpecsViewState
st
     ExperimentSpecsWriter -> Experiment -> HtmlWriter ()
write ExperimentSpecsWriter
writer Experiment
exp

header :: ExperimentSpecsViewState -> Int -> HtmlWriter ()
header :: ExperimentSpecsViewState -> Int -> HtmlWriter ()
header ExperimentSpecsViewState
st Int
index =
  do String -> HtmlWriter () -> HtmlWriter ()
writeHtmlHeader3WithId (String
"id" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
index) (HtmlWriter () -> HtmlWriter ()) -> HtmlWriter () -> HtmlWriter ()
forall a b. (a -> b) -> a -> b
$
       String -> HtmlWriter ()
writeHtmlText (ExperimentSpecsView -> String
experimentSpecsTitle (ExperimentSpecsView -> String) -> ExperimentSpecsView -> String
forall a b. (a -> b) -> a -> b
$ ExperimentSpecsViewState -> ExperimentSpecsView
experimentSpecsView ExperimentSpecsViewState
st)
     let description :: String
description = ExperimentSpecsView -> String
experimentSpecsDescription (ExperimentSpecsView -> String) -> ExperimentSpecsView -> String
forall a b. (a -> b) -> a -> b
$ ExperimentSpecsViewState -> ExperimentSpecsView
experimentSpecsView ExperimentSpecsViewState
st
     Bool -> HtmlWriter () -> HtmlWriter ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
description) (HtmlWriter () -> HtmlWriter ()) -> HtmlWriter () -> HtmlWriter ()
forall a b. (a -> b) -> a -> b
$
       HtmlWriter () -> HtmlWriter ()
writeHtmlParagraph (HtmlWriter () -> HtmlWriter ()) -> HtmlWriter () -> HtmlWriter ()
forall a b. (a -> b) -> a -> b
$
       String -> HtmlWriter ()
writeHtmlText String
description

-- | Get the TOC item     
experimentSpecsTOCHtml :: ExperimentSpecsViewState -> Int -> HtmlWriter ()
experimentSpecsTOCHtml :: ExperimentSpecsViewState -> Int -> HtmlWriter ()
experimentSpecsTOCHtml ExperimentSpecsViewState
st Int
index =
  HtmlWriter () -> HtmlWriter ()
writeHtmlListItem (HtmlWriter () -> HtmlWriter ()) -> HtmlWriter () -> HtmlWriter ()
forall a b. (a -> b) -> a -> b
$
  String -> HtmlWriter () -> HtmlWriter ()
writeHtmlLink (String
"#id" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
index) (HtmlWriter () -> HtmlWriter ()) -> HtmlWriter () -> HtmlWriter ()
forall a b. (a -> b) -> a -> b
$
  String -> HtmlWriter ()
writeHtmlText (ExperimentSpecsView -> String
experimentSpecsTitle (ExperimentSpecsView -> String) -> ExperimentSpecsView -> String
forall a b. (a -> b) -> a -> b
$ ExperimentSpecsViewState -> ExperimentSpecsView
experimentSpecsView ExperimentSpecsViewState
st)