module Main where

import System.Console.GetOpt
import System.Environment
import System.IO
import FindCopies
import Linspire.Unix.Process
import qualified Data.ByteString.Char8 as B

main =
    getArgs >>= doFind . computeFlags
    where
      computeFlags args =
          case getOpt Permute opts args of
            (o, [orig, copy], []) -> (orig, copy, o)
            (_, _, []) -> error usage
            (_, _, errs) -> error (concat errs ++ usage)
      doFind (orig, copy, flags)
          | elem Help flags = putStrLn usage
          | elem IfSameContent flags = copyStatus (sameContent flags) orig copy
          | elem IfSameName flags = copyStatus (sameName flags) orig copy
          | elem IfSamePath flags = copyStatus (samePath flags) orig copy
          | elem Counts flags = copyStatus showCounts orig copy
          | True = copyStatus showStatus orig copy
      usage = usageInfo "Usage: findCopes [options] origdir copydir" opts

sameContent flags (SameContent copyPath origPath) = operation flags origPath copyPath
sameContent flags x = sameName flags x
sameName flags (SameNameAndContent copyPath origPath) = operation flags origPath copyPath
sameName flags x = samePath flags x
samePath flags (SamePathAndContent copyPath origPath) = operation flags origPath copyPath
samePath flags x = return ()

operation flags origPath copyPath
    | elem Print flags = hPutStrLn stderr ("orig: " ++ origPath ++ ", copy: " ++ copyPath)
    | elem Symlink flags = command ("ln -s -f " ++ show origPath ++ " " ++ show copyPath)
    | elem Hardlink flags = command ("ln -f " ++ show origPath ++ " " ++ show copyPath)
    | elem Remove flags = command ("rm -f " ++ show copyPath)
    | True = hPutStrLn stderr ("(Missing operation argument) orig: " ++ origPath ++ ", copy: " ++ copyPath)

command s = do
  result <- lazyCommand s []
  let output = B.unpack (B.concat (outputOnly result))
  case exitCodeOnly result of
    (ExitFailure n : _) -> error (s ++ " -> " ++ show n ++ "\n" ++ output)
    _ -> hPutStr stderr (s ++ output) >> return ()

data Flag
    = Help
    | Counts
    | IfSameContent
    | IfSameName
    | IfSamePath
    | Remove
    | Hardlink
    | Symlink
    | Print
    deriving Eq

opts :: [OptDescr Flag]
opts =
    [Option ['h'] ["help"] (NoArg Help) "Print help message and exit.",
     Option [] ["remove"] (NoArg Remove) "Remove all matching copies",
     Option [] ["hardlink"] (NoArg Symlink) "Replace all matching copies with hard links",
     Option [] ["symlink"] (NoArg Symlink) "Replace all matching copies with symlinks",
     Option [] ["print"] (NoArg Print) "Print all matching copies",
     Option [] ["same-content"] (NoArg IfSameContent) "Files match if they have the same content",
     Option [] ["same-name"] (NoArg IfSameName) "Files match if they have the same content and name",
     Option [] ["same-path"] (NoArg IfSamePath) "Files match if they have the same content and path",
     Option [] ["counts"] (NoArg Counts) "Print the count of each status."]

