{-|
Module      : Pansite.PathPattern
Description : GNU Make-style path patterns
Copyright   : (C) Richard Cook, 2017-2018
Licence     : MIT
Maintainer  : rcook@rcook.org
Stability   : experimental
Portability : portable
-}

{-# LANGUAGE CPP #-}

module Pansite.PathPattern
    ( PathPattern
    , pathPattern
    , pathPatternStem
    , substituteStem
    , (%%>>)
    ) where

import           Data.String.Utils
import           Development.Shake
import           Development.Shake.FilePath
import           Pansite.Util

newtype PathPattern = PathPattern String deriving Show

makeToken :: String
makeToken = "%"

shakeToken :: String
shakeToken = "*"

-- | Convert string to path pattern
--
-- Examples:
--
-- >>> import Data.Either
-- >>> isRight $ pathPattern "%"
-- True
-- >>> isRight $ pathPattern "aaa"
-- True
-- >>> isLeft $ pathPattern "%%"
-- True
-- >>> isLeft $ pathPattern "%aaa%"
-- True
pathPattern :: String -> Either String PathPattern
pathPattern s
    | let n = countOccurrences s makeToken in n == 0 || n == 1 = Right $ PathPattern s
    | otherwise = Left $ "Invalid path pattern " ++ s

-- | Substitute stem in path pattern
--
-- Examples:
--
-- >>> Right p = pathPattern "/aaa/bbb/%/ddd/eee/"
-- >>> substituteStem "ccc" p
-- "/aaa/bbb/ccc/ddd/eee/"
substituteStem :: String -> PathPattern -> FilePath
substituteStem stem (PathPattern s) = replace makeToken stem s

(%%>>) :: PathPattern -> (FilePath -> Action ()) -> Rules ()
(%%>>) (PathPattern s) b = replace makeToken shakeToken s %> b
infix 1 %%>>

#if defined(OS_MACOS) || defined(OS_LINUX)
-- | Stem of pattern and path
--
-- Examples:
--
-- >>> Right p = pathPattern "C:/aaa/bbb/%.txt"
-- >>> pathPatternStem p "C:/aaa/bbb/stem.txt"
-- "stem"
#elif defined(OS_WINDOWS)
-- TODO: Enforce the wildcard token via the types!
-- | Find stem of path and rule
--
-- Examples:
--
-- >>> Right p0 = pathPattern "C:/aaa/bbb/%.txt"
-- >>> pathPatternStem p0 "C:\\aaa\\bbb\\stem.txt"
-- "stem"
-- >>> Right p1 = pathPattern "C:\\aaa\\bbb\\%.txt"
-- >>> pathPatternStem p1 "C:/aaa/bbb/stem.txt"
-- "stem"
#else
#error Unsupported platform
#endif
pathPatternStem :: PathPattern -> FilePath -> String
pathPatternStem (PathPattern s) path = let (stem, _) = stems (toNative path) (toNative s) in stem