{-# LANGUAGE TemplateHaskell #-}
-- | Defines types and functions to gather all the information needed for printing.
module Language.Drasil.Printing.PrintingInformation (
    Notation(..), HasPrintingOptions(..)
  , PrintingConfiguration, notation
  , PrintingInformation
  , sysdb, stg, configuration
  , piSys, refFind
  , defaultConfiguration, plainConfiguration
) where

import Control.Lens (makeLenses, Lens', (^.))
import qualified Data.Map.Strict as M
import Data.Maybe (fromMaybe)

import Drasil.Database (UID, ChunkDB)
import Language.Drasil (Stage(..), Reference)

-- | Notation can be scientific or for engineering.
data Notation = Scientific
              | Engineering

-- | Able to be printed.
class HasPrintingOptions c where
    -- | Holds the printing notation.
    getSetting :: Lens' c Notation

-- | Holds the printing configuration.
newtype PrintingConfiguration = PC { PrintingConfiguration -> Notation
_notation :: Notation }
makeLenses ''PrintingConfiguration

-- | Finds the notation used for the 'PrintingConfiguration'.
instance HasPrintingOptions  PrintingConfiguration where getSetting :: Lens' PrintingConfiguration Notation
getSetting = (Notation -> f Notation)
-> PrintingConfiguration -> f PrintingConfiguration
Iso' PrintingConfiguration Notation
notation

-- | Printing information contains a database, a stage, and a printing configuration.
data PrintingInformation =
  PI { PrintingInformation -> ChunkDB
_sysdb :: ChunkDB
     , PrintingInformation -> Map UID Reference
_refTable :: M.Map UID Reference
     , PrintingInformation -> Stage
_stg :: Stage
     , PrintingInformation -> PrintingConfiguration
_configuration :: PrintingConfiguration
     }
makeLenses ''PrintingInformation

-- | Finds the notation used for the 'PrintingConfiguration' within the 'PrintingInformation'.
instance HasPrintingOptions  PrintingInformation where getSetting :: Lens' PrintingInformation Notation
getSetting  = (PrintingConfiguration -> f PrintingConfiguration)
-> PrintingInformation -> f PrintingInformation
Lens' PrintingInformation PrintingConfiguration
configuration ((PrintingConfiguration -> f PrintingConfiguration)
 -> PrintingInformation -> f PrintingInformation)
-> ((Notation -> f Notation)
    -> PrintingConfiguration -> f PrintingConfiguration)
-> (Notation -> f Notation)
-> PrintingInformation
-> f PrintingInformation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Notation -> f Notation)
-> PrintingConfiguration -> f PrintingConfiguration
forall c. HasPrintingOptions c => Lens' c Notation
Lens' PrintingConfiguration Notation
getSetting

-- | Builds a document's printing information based on the system information.
piSys :: ChunkDB -> M.Map UID Reference -> Stage -> PrintingConfiguration -> PrintingInformation
piSys :: ChunkDB
-> Map UID Reference
-> Stage
-> PrintingConfiguration
-> PrintingInformation
piSys = ChunkDB
-> Map UID Reference
-> Stage
-> PrintingConfiguration
-> PrintingInformation
PI

refFind :: UID -> PrintingInformation -> Reference
refFind :: UID -> PrintingInformation -> Reference
refFind UID
u PrintingInformation
pinfo = Reference -> Maybe Reference -> Reference
forall a. a -> Maybe a -> a
fromMaybe ([Char] -> Reference
forall a. HasCallStack => [Char] -> a
error ([Char] -> Reference) -> [Char] -> Reference
forall a b. (a -> b) -> a -> b
$ [Char]
"`" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ UID -> [Char]
forall a. Show a => a -> [Char]
show UID
u [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"` not found in Reference table!!!")
  (Maybe Reference -> Reference) -> Maybe Reference -> Reference
forall a b. (a -> b) -> a -> b
$ UID -> Map UID Reference -> Maybe Reference
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup UID
u (Map UID Reference -> Maybe Reference)
-> Map UID Reference -> Maybe Reference
forall a b. (a -> b) -> a -> b
$ PrintingInformation
pinfo PrintingInformation
-> Getting
     (Map UID Reference) PrintingInformation (Map UID Reference)
-> Map UID Reference
forall s a. s -> Getting a s a -> a
^. Getting (Map UID Reference) PrintingInformation (Map UID Reference)
Lens' PrintingInformation (Map UID Reference)
refTable

-- | Default configuration is for engineering.
defaultConfiguration :: PrintingConfiguration
defaultConfiguration :: PrintingConfiguration
defaultConfiguration = Notation -> PrintingConfiguration
PC Notation
Engineering

-- | Simple printing configuration is scientific.
plainConfiguration :: PrintingConfiguration
plainConfiguration :: PrintingConfiguration
plainConfiguration = Notation -> PrintingConfiguration
PC Notation
Scientific