{-# LANGUAGE TemplateHaskell #-}
-- | Defines types and functions to gather all the information needed for printing.
module Language.Drasil.Printing.PrintingInformation (
    Notation(..), HasPrintingOptions(..)
  , PrintingConfiguration, notation
  , PrintingInformation
  , syst, 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)
import Language.Drasil (Stage(..), Reference)
import Drasil.System (System, refTable)

-- | 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 -> System
_syst :: System
                         , 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 :: System -> Stage -> PrintingConfiguration -> PrintingInformation
piSys :: System -> Stage -> PrintingConfiguration -> PrintingInformation
piSys = System -> 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
^. (System -> Const (Map UID Reference) System)
-> PrintingInformation
-> Const (Map UID Reference) PrintingInformation
Lens' PrintingInformation System
syst ((System -> Const (Map UID Reference) System)
 -> PrintingInformation
 -> Const (Map UID Reference) PrintingInformation)
-> ((Map UID Reference
     -> Const (Map UID Reference) (Map UID Reference))
    -> System -> Const (Map UID Reference) System)
-> Getting
     (Map UID Reference) PrintingInformation (Map UID Reference)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map UID Reference
 -> Const (Map UID Reference) (Map UID Reference))
-> System -> Const (Map UID Reference) System
forall c. HasSystem c => Lens' c (Map UID Reference)
Lens' System (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