module System.FileSystem.Computations
     ( putPath
     , getFl
     , getDirCnt
     , checkFExist
     , checkDExist
     , newDir
     , rmvPath
     , rmvDir
     , rmvFile
     , rnmPath
     , rnmDir
     , rnmFile
       ) where

import Control.Monad.Identity (runIdentity)
import Control.Monad.State (runStateT,modify,put)
import Control.Arrow ( (***) , first , second )
import Control.Applicative ( (<$>) , pure )
import Data.Maybe (isJust)
import Data.Either (partitionEithers)
--
import System.FileSystem.Types
import System.FileSystem.Operators
import System.FileSystem.Utils
import System.FileSystem.Class

putPath :: FSMonad m => Path -> m ()
putPath = modifyFS . (<:)

getFl :: (Functor m, FSMonad m) => FPath -> m (Maybe File)
getFl = apgetFS . (?:)

searchDirCnt :: DirPath -> FileSystem -> Maybe ([DirName],[FileName])
searchDirCnt [] = Just . (fmap fst *** fmap getFN). partitionEithers . dirCnt
searchDirCnt (x:xs) = maybe Nothing (searchDirCnt xs) . (x=:)

getDirCnt :: (Functor m, FSMonad m) => DirPath -> m (Maybe ([DirName], [FileName]))
getDirCnt = apgetFS . searchDirCnt

checkFExist :: (Functor m, FSMonad m) => (DirPath, FileName) -> m Bool
checkFExist (dp,fn) = maybe False (elem fn . snd) <$> getDirCnt dp

checkDExist :: (Functor m, FSMonad m) => DirPath -> m Bool
checkDExist = fmap isJust . getDirCnt

newDir :: FSMonad m => DirPath -> m ()
newDir = putPath . (`Path`Nothing)

rmvPath :: FSMonad m => Path -> m ()
rmvPath = modifyFS . (-:)

rmvDir :: FSMonad m => DirPath -> m () 
rmvDir = rmvPath . (`Path`Nothing)

rmvFile :: FSMonad m => FPath -> m ()
rmvFile = rmvPath . uncurry Path . second (Just . File emptyFD)

rnmPath :: (Functor m, FSMonad m) => ([String], [String], Bool) -> m Bool
rnmPath = bind (uncurry (>>) . (putFS *** return)) . apgetFS . (<-:)

rnmDir :: (Functor m, FSMonad m) => (DirPath, DirPath) -> m Bool
rnmDir = rnmPath . tup3 True

rnmFile :: (Functor m, FSMonad m) => (FPath, FPath) -> m Bool
rnmFile = let f = uncurry (++) . second pure
          in  rnmPath . tup3 False . pairMap f