-- |
-- Module      :  HsIndex.Types
-- Copyright   :  Jean-Luc JOULIN 2018-2020
-- License     :  General Public Licence (GPLv3)
-- Maintainer  :  Jean-Luc JOULIN  <jean-luc-joulin@orange.fr>
-- Stability   :  alpha
-- Portability :  portable
-- The definition of main types for HsIndex.




module HsIndex.Types where


import           Text.Parsec
import           Text.Parsec.String

import           Data.Char
import qualified Data.Text                     as T

--
-- The main data structure of an index is made like this
--
-- * Section ""
--   
--    * Subsection ""
--
--        * Entry "" [4]
--
--        * Entry "" [17,12]
--
--            * SubEntry "" [21]
--
--                  * SubSubEntry "" [22]
--
--            * SubEntry "" [29]
--
--    * Subsection ""
--
--
-- * Section B"
--
--    * ....
--
-- * ....
--
--
-- Sections are made to store SubSections starting with the same first letter.
--
-- SubSections are made to store Entries starting with the same two letters.
--
-- Entry is made to store a word, it's pages numbers and a list of SubEntries. It's equivalent to "imakeidx" items.
--
-- SubEntry is made to store a word, it's pages numbers and a list of SubSubEntries. It's equivalent to "imakeidx" subitems.
--
-- SubSubEntry is made to store a word and it's pages numbers. It's equivalent to "imakeidx" subsubitems.
--
--
-- This data structure is deep enough to comply with "imakeidx" LaTeX package.
--











-- | The type to describe the style of the Index
--
-- preamble
--
-- prefix heading layer1 suffix
-- 
-- name1 delimiters 1, 3, 4
--
-- name2 delimiters    4, 9
--
-- name3 delimiters   9, 12
--
-- postamble
--
data IndexStyle = 
  IndexStyle  { idxPreamble     :: T.Text  -- ^ The preamble
              , idxPostamble    :: T.Text  -- ^ The postamble
              , idxHeadingFlag0 :: Heading -- ^ The flag for the layer 0 heading, in connection with 'IndexSection's
              , idxHeadingFlag1 :: Heading -- ^ The flag for the layer 1 heading, in connection with 'IndexSubSection's
              , idxHeadingPreL0 :: T.Text  -- ^ The prefix for the Layer 0 heading, in connection with 'IndexSection's
              , idxHeadingSufL0 :: T.Text  -- ^ The suffix for the Layer 0 heading, in connection with 'IndexSection's
              , idxHeadingPreL1 :: T.Text  -- ^ The prefix for the Layer 1 heading, in connection with 'IndexSubSection's
              , idxHeadingSufL1 :: T.Text  -- ^ The suffix for the Layer 1 heading, in connection with 'IndexSubSection's
              , idxSymhead      :: T.Text  -- ^ The title for the "symbols" section
              , idxNumhead      :: T.Text  -- ^ The title for the "numbers" section
              , idxGroupSkip0   :: T.Text  -- ^ The skip command after a layer 0 group ('IndexSection')
              , idxGroupSkip1   :: T.Text  -- ^ The skip command after a layer 1 group ('IndexSubSection')
              , idxItem0        :: T.Text  -- ^ The command to place before the index "items"
              , idxItem1        :: T.Text  -- ^ The command to place before the index "subitems"
              , idxItem2        :: T.Text  -- ^ The command to place before the index "subsubitems"
              , idxItem01       :: T.Text  -- ^ The command to place between an index "items" and an index "subitems"
              , idxItem12       :: T.Text  -- ^ The command to place between an index "subitems" and an index "subsubitems"
              , idxDelim0       :: T.Text  -- ^ The delimiter between the name and the pages numbers for "items"
              , idxDelim1       :: T.Text  -- ^ The delimiter between the name and the pages numbers for "subitems"
              , idxDelim2       :: T.Text  -- ^ The delimiter between the name and the pages numbers for "subsubitems"
              , idxDelimn       :: T.Text  -- ^ The delimiter between pages numbers.
              , idxDelimr       :: T.Text  -- ^ The delimiter between pages range.
              , idxEncapPre     :: T.Text
              , idxEncapSuf     :: T.Text
              }


-- | The list of chars to define a language.
data LangDef = LangDef  { lstLetters  :: [Char]           -- ^ Chars considered as letters.
                        , lstNumbers  :: [Char]           -- ^ Chars considered as numbers.
                        , lstSymbols  :: Maybe [Char]     -- ^ Chars considered as symbols.
                        , lstSubs     :: [(Char,String)]       -- ^ List of substitutions to perform.
                        , lstSecOrder :: [Section]
                        }


-- | The style of a heading.
data Heading = None        -- ^ No heading
             | UpperCase   -- ^ Upper case heading
             | LowerCase   -- ^ Lower case heading
             deriving (Eq)


-- | The category of a section.
--
-- A section can be one of these three categories :
--
-- * Letters
--
-- * Numbers
--
-- * Symbols
--
data Section = Letters
             | Numbers
             | Symbols
             deriving (Eq, Show)

-- | An alias for a list of 'IndexSection's
type Index = [IndexSection]


-- | The type for a section.
data IndexSection = 
    IndexSection  { secTitle       :: T.Text              -- ^ The section title.
                  , secSubSections :: [IndexSubSection]   -- ^ The subsections.
                  }
                  deriving (Show)

-- | The type for a subsection.
data IndexSubSection = 
  IndexSubSection { subSecTitle   :: T.Text            -- ^ The subsection title.
                  , subSecEntries :: [IndexItem]       -- ^ The entries.
                  }
                  deriving (Show)
                  
-- | The type for an item.
data IndexItem =
        IndexItem { itemName        :: T.Text            -- ^ The name of the index item.
                  , itemEqui        :: (Section, T.Text) -- ^ The equivalent name and the section of the item.
                  , itemPageCommand :: T.Text            -- ^ The command to insert before page number
                  , itemPages       :: [Int]             -- ^ The pages numbers it refers to.
                  , itemContent     :: [IndexSubItem]    -- ^ The subitems.
                  }
                  deriving (Show)

-- | The type for a subitem.
data IndexSubItem = 
    IndexSubItem  { subItemName        :: T.Text            -- ^ The name of the index subitem.
                  , subItemEqui        :: (Section, T.Text) -- ^ The equivalent name and the section of the subitem.
                  , subItemPageCommand :: T.Text            -- ^ The command to insert before page number
                  , subItemPages       :: [Int]             -- ^ The pages numbers it refers to.
                  , subItemContent     :: [IndexSubSubItem] -- ^ The subsubitems.
                  }
                  deriving (Show)
                  
-- | The type for a subsubitem.
data IndexSubSubItem = 
  IndexSubSubItem { subSubItemName        :: T.Text            -- ^ The name of the index subsubitem.
                  , subSubItemEqui        :: (Section, T.Text) -- ^ The equivalent name and the section of the subsubitem.
                  , subSubItemPageCommand :: T.Text            -- ^ The command to insert before page number
                  , subSubItemPages       :: [Int]             -- ^ The pages numbers it refers to.
                  }
                  deriving (Show)


-- | The type of index to use
data IndexType = StyleBasic           -- ^ The default basic style
               | StyleDouble          -- ^ The default double header style
               | Stylecustom FilePath -- ^ A custom style (path to the style file).


-- | A state to accumulate the 'Section' order.
data PermState = PermState{ order::[Section]}

-- | The empty state
emptyPermState = PermState []