module Distribution.CommandLine
    ( writeManpages
    , writeBashCompletions
    , setManpathBash
    , setManpathZsh
    , setManpathFish
    , setManpath
    , writeTheFuck
    ) where

import           Control.Applicative
import           Control.Monad       (unless, void, when)
import           System.Directory    (createDirectoryIfMissing, doesDirectoryExist, doesFileExist)
import           System.Environment  (lookupEnv)
import           System.Info         (os)
import           System.Process      (readCreateProcessWithExitCode, shell)

rules :: String
rules =
    "import re\n" ++
    "from thefuck.utils import replace_argument\n" ++
    "\n" ++
    "def match(command):\n" ++
    "    return ('Did you mean this?' in command.output and 'Invalid argument' in command.output)\n" ++
    "\n" ++
    "def get_new_command(command):\n" ++
    "    broken = command.script_parts[1]\n" ++
    "    fix = re.findall(r'    ([a-zA-z]*)', command.output)[0]\n" ++
    "\n" ++
    "    return replace_argument(command.script, broken, fix)\n" ++
    "\n" ++
    "enabled_by_default = True\n" ++
    "\n" ++
    "priority = 100"

-- | Write a set of rules based on
-- [optparse-applicative](http://hackage.haskell.org/package/optparse-applicative)
-- for the command-line tool
-- [fuck](https://pypi.python.org/pypi/thefuck/).
writeTheFuck :: IO ()
writeTheFuck = do
    h <- lookupEnv "HOME"
    case h of
        Just h' -> do
            proceed <- doesDirectoryExist (h' ++ "/.config/thefuck/rules")
            when proceed $
                writeFile (h' ++ "/.config/thefuck/rules/optparse-applicative.py") rules
        Nothing -> pure ()

-- | Add a line exporting the modified @MANPATH@ to the user's @bashrc@, if it
-- does not exist already.
--
-- @since 0.2.1.0
setManpathBash :: IO ()
setManpathBash = setManpathGeneric ".bashrc"

setManpathZsh :: IO ()
setManpathZsh = setManpathGeneric ".zshrc"

setManpathFish :: IO ()
setManpathFish = setManpathGeneric ".config/fish/config.fish"

setManpath :: IO ()
setManpath = setManpathBash
{-# DEPRECATED setManpath "Use setManpathBash or setManpathZsh" #-}

setManpathGeneric :: FilePath -> IO ()
setManpathGeneric fp = do
    home <- lookupEnv "HOME"
    case home of
        Just x -> do
            let bashRc = x ++ "/" ++ fp
            b <- doesFileExist bashRc
            when b $ do
                config <- readFile bashRc
                unless ("#manpath updated by cli-setup" `elem` lines config)
                    (appendFile bashRc "\n#manpath updated by cli-setup\nexport MANPATH=$HOME/.local/share:$MANPATH\n" *>
                    void (readCreateProcessWithExitCode (shell $ "MANPATH=" ++ x ++ "/.local/share mandb") ""))
        Nothing -> pure ()

-- | As an example, if your source tarball contains a file @man/madlang.1@ you
-- could use
--
-- > writeManpages "man/madlang.1" "madlang.1"
writeManpages :: FilePath -- ^ Source File
              -> FilePath -- ^ Manpage file name
              -> IO ()
writeManpages p p' = do
    mp' <- manPath
    case mp' of
        Just mp -> do
            createDirectoryIfMissing True mp
            writeFile (mp ++ "/" ++ p') =<< readFile p
        Nothing -> pure ()

manPathLinux :: IO (Maybe FilePath)
manPathLinux = do
    home <- lookupEnv "HOME"
    case home of
        Just h  -> pure $ Just (h ++ "/.local/share/man/man1")
        Nothing -> pure Nothing

manPath :: IO (Maybe FilePath)
manPath =
    case os of
        "linux"  -> manPathLinux
        "darwin" -> pure $ Just "/usr/local/share/man/man1"
        _        -> pure Nothing

-- | Add a line to the user's @bashrc@ so that command-line completions work
-- automatically.
writeBashCompletions :: String -- ^ Executable name
                     -> IO ()
writeBashCompletions exeName = do
    home <- lookupEnv "HOME"
    case home of
        Just x -> do
            let bashRc = x ++ "/.bashrc"
            b <- doesFileExist bashRc
            when b $ do
                config <- readFile bashRc
                unless (("# Added for " ++ exeName) `elem` lines config)
                    (appendFile bashRc ("\n# Added for " ++ exeName ++ "\neval \"$(" ++ exeName ++ " --bash-completion-script " ++ exeName ++ ")\"\n"))
        Nothing -> pure ()