FilePaths

module FilePaths(AFilePath,rootPath,aFilePath,filePath,
                 compactPath,isAbsolute,joinPaths,pathRelativeTo,
		 extendPath,pathTail,pathHead,pathLength) where
import Data.List(intersperse)
--import IO(openDirectory, statFile)
--import ListUtil(chopList,breakAt)
import Utils(segments)

newtype AFilePath = P [String] deriving (Eq,Ord)
-- data AFilePath = Root | Cwd | AFilePath :/ String

aFilePath :: FilePath -> AFilePath
aFilePath = P . splitpath

rootPath = P [""]

filePath :: AFilePath -> FilePath
filePath (P path) = joinpath path

compactPath (P path) = P (compactpath path)

extendPath (P path) node = P (node:path)

pathTail :: AFilePath -> String
pathTail (P []) = "." -- ??
pathTail (P [""]) = "/" -- ??
pathTail (P (t:_)) =  t

pathHead (P []) = (P []) -- ??
pathHead (P (t:h)) = P h

pathLength (P path) = length path

isAbsolute (P ns) = isabsolute ns

joinPaths (P parent) (P child) =
 if isabsolute child
 then P child
 else P (child++parent) -- compactpath?

P file `pathRelativeTo` P dir =
    if take dirlen rfile == rdir
    then P (reverse (drop dirlen rfile))
    else P file
  where
    rdir = reverse dir
    rfile = reverse file
    dirlen = length rdir

isabsolute [] = False
isabsolute ns = null (last ns)

splitpath = reverse . segments (/='/')

joinpath [] = "."
joinpath [""] = "/"
joinpath ns = concat (intersperse "/" (reverse ns))

compactpath [] = []
compactpath (".." : xs) =
  case compactpath xs of
    [""] -> [""] -- parent of root directory, stay in root directory
    ys@("..":_) -> "..":ys -- relative path to grandparent, keep ".."
    _:ys -> ys -- parent of child, optimize
    ys -> "..":ys -- other, keep ".."
--compactpath ["..",""] = [""] -- parent of root directory
--compactpath (".." : "." : xs) = compactpath ("..":xs)
--compactpath (".." : x : xs) | x /= ".." = compactpath xs
compactpath ("" : xs@(_:_)) = compactpath xs
compactpath ("." : xs) = compactpath xs
compactpath (x : xs) = x : compactpath xs

{-
ls s =
    let paths = map (: s) . sort . filter (/= ".")
    in  case openDirectory (joinpath s) of
          Right files -> paths files
          Left msg -> [msg : s]

isdir s =
    case statFile (joinpath s) of
      Right ns -> let mode = ns !! (3 - 1)
                  in  bitand mode 61440 == 16384
      Left _ -> False

-}