--
-- GNU General Public License (GPLv3)
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) “AS IS” AND ANY EXPRESS OR 
-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
-- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-- IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
-- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 
-- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-- |
-- Module      :  HsIndex.Files
-- Copyright   :  Jean-Luc JOULIN 2018-2019
-- License     :  General Public Licence (GPLv3)
-- Maintainer  :  Jean-Luc JOULIN  <jean-luc-joulin@orange.fr>
-- Stability   :  alpha
-- Portability :  portable
-- Module for reading input and style files.
--
-- This module also provide the function to write output file.
--




module HsIndex.Files
    (
    -- * Read functions
      readIndexFile
    , readStyleFile
    , readDefinitionFile
    , readAllFile

    -- * Writing function
    , writeIndex
    )
    where

import           Data.Char
import           HsIndex.Functions
import           HsIndex.Show
import           HsIndex.Parser
import           HsIndex.Types
import           Text.Parsec
import           Text.Parsec.String
import           System.Directory               ( doesFileExist )
import qualified Data.Text                     as T
import qualified Data.Text.IO                  as T
import           Data.Functor.Identity


-- | Read an index input file.
readIndexFile :: FilePath                     -- ^ The path to the index file.
              -> ParsecT String () Identity t -- ^ The parser to apply on the file to extract datas.
              -> (t -> IO ())                 -- ^ List of operations to perform on parsed datas.
              -> IO ()
readIndexFile fidx parsfun fun = do
    e <- doesFileExist fidx
    if e
        then do
            f <- readFile fidx
            case parse parsfun "(stdin)" f of
                Left  err  -> do
                    putStrLn $ "/!\\ ERROR reading Index file : " ++ fidx
                    print err
                Right resu -> fun resu
        else
            putStrLn
            $  "/!\\ ERROR the Index file : "
            ++ fidx
            ++ " does not exist !\n"


-- | Read a style input file
--
-- If no path is provided for the style file, the standard style 'styleBasic' is applied.
--
readStyleFile :: IndexType             -- ^ The type of style.
              -> (IndexStyle -> IO ()) -- ^ Operations to apply with the parsed style.
              -> IO ()
readStyleFile StyleBasic         fun = do
    putStrLn "Using the default basic style"
    fun styleBasic

readStyleFile StyleDouble        fun = do
    putStrLn "Using the default double letters style"
    fun styleDoubleHeading



readStyleFile (Stylecustom fsty) fun = do
    e <- doesFileExist fsty
    if e
        then do
            f <- readFile fsty
            case parse (parseStyleFile styleBasic) "(stdin)" f of
                Left  err  -> do
                    putStrLn $ "/!\\ ERROR reading Style file : " ++ fsty
                    print err
                Right resu -> fun resu
        else
            putStrLn
            $  "/!\\ ERROR the Style file : "
            ++ fsty
            ++ " does not exist !\n"


-- | Read a language definition input file.
readDefinitionFile :: FilePath           -- ^ The path to the definition file.
                   -> (LangDef -> IO ()) -- ^ Operations to apply with the parsed style.
                   -> IO ()
readDefinitionFile fdef fun = do
    e <- doesFileExist fdef
    if e
        then do
            f <- readFile fdef
            case runParser (parseLanguageFile) emptyPermState "(stdin)" f of
                Left  err  -> do
                    putStrLn $ "/!\\ ERROR reading Definition file : " ++ fdef
                    print err
                Right resu -> fun resu
        else
            putStrLn
            $  "/!\\ ERROR the Definition file : "
            ++ fdef
            ++ " does not exist !\n"


-- | Read both an index input file and style file.
--
-- If no path is provided for the style file, the standard style 'styleBasic' is applied.
--
readAllFile :: FilePath                     -- ^ The path to the index file.
            -> IndexType                    -- ^ The type of index.
            -> ParsecT String () Identity t -- ^ The parser to apply on the index file.
            -> (t -> IndexStyle -> IO ())   -- ^ Operations to apply with the parsed index data and style.
            -> IO ()
readAllFile fidx mbfsty parsfun fun =
    readIndexFile fidx parsfun (readStyleFile mbfsty . fun)


-- | Write the sorted entries in a output file with the format provided in the `IndexStyle`.
writeIndex :: FilePath   -- ^ The path to the output file
           -> IndexStyle -- ^ The style file.
           -> Bool       -- ^ Automatic conversion to pages ranges
           -> Index      -- ^ The index.
           -> IO ()
writeIndex file style rng sec = do
    putStrLn $ "Writing index to File : " ++ file
    T.writeFile file $ showIndex style rng sec


