-----------------------------------------------------------------------------
-- |
-- Module      :  Static.Resources.Spec
-- Copyright   :  (c) Scrive 2012
-- License     :  BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  :  mariusz@scrive.com
-- Stability   :  development
-- Portability :  portable
--
-- Parsing static resources spec.
--
-- * Line starting with word set is start of 'ResourceSet' definition.
--
-- * Line starting css, js or jsx defines 'Resource'.
--
-- * Line starting with ignore defines that some file should be ignored by checker.
--
-- * ALL other lines are ignored
--
-- Sample spec
-- 
-- > ignore main.css
-- >
-- > set a
-- >   js  a.js 
-- >   css a.css
-- >   css common.css
-- >
-- > set b
-- >   js  b.js    
-- >   css b.css
-- >   css common.css
--

--

module Static.Resources.Spec (
                               -- * Parsing
                                 parseSpec
                        ) where


import Static.Resources.Types
import Data.List
import Data.Char
import Data.Generics.Builders

setPrefix :: String
setPrefix = "set"

ignorePrefix :: String
ignorePrefix = "ignore"


typePrefix :: ResourceType -> String
typePrefix CSS = "css"
typePrefix JS  = "js"
typePrefix JSX = "jsx"
typePrefix LESS = "less"



parseSpec :: FilePath -> IO ResourceSpec
parseSpec specPath = do
    c <- readFile specPath
    return $ foldl parse (ResourceSpec [] []) $ map trim $ lines c
    where
      trim = (reverse . dropWhile isSpace) . (reverse . dropWhile isSpace)
      clear pr s = trim $ drop (length pr) s
      parse :: ResourceSpec -> String -> ResourceSpec
      parse (ResourceSpec rs is) s
          | (ignorePrefix ++ " ") `isPrefixOf` s  = ResourceSpec rs ((clear ignorePrefix s) : is)
          | (setPrefix ++ " ") `isPrefixOf` s  = ResourceSpec ((ResourceSet (clear setPrefix s) []) : rs)  is
          | otherwise = case find (\t -> (typePrefix t ++ " ") `isPrefixOf` s) constrs of
                          Just rt -> case rs of
                                       (r:rs') -> ResourceSpec (r {resources = (resources r) ++ [Resource rt (clear (typePrefix rt) s )]}:rs') is
                                       _ -> error $ "Resource " ++ clear (typePrefix rt) s  ++ " defined outside resource set in file " ++ specPath
                          _ -> ResourceSpec rs is