{-# LANGUAGE Rank2Types #-}

-- | Functions to remove from your life.

module Life.Main.Remove
       ( lifeRemove
       ) where

import Lens.Micro.Platform (Lens', (%~))
import Path (Abs, Path, Rel)
import Path.IO (getHomeDir, makeRelative, removeDirRecur, removeFile, resolveDir, resolveFile)

import Life.Configuration (LifeConfiguration, LifePath (..), directories, files, parseHomeLife,
                           writeGlobalLife)
import Life.Github (removeFromRepo, withSynced)
import Life.Message (abortCmd, warningMessage)
import Life.Shell (LifeExistence (..), whatIsLife)

import qualified Data.Set as Set

-- | Remove path from existing life-configuration file.
lifeRemove :: LifePath -> IO ()
lifeRemove lPath = whatIsLife >>= \case
    -- if one of them is missing -- abort
    NoLife -> abortCmd "remove" ".life and docfiles/ do not exist"
    OnlyLife _ -> abortCmd "remove" "dotfiles/ directory doesn't exist"
    OnlyRepo _ -> abortCmd "remove" ".life file doesn't exist"
    -- actual life remove process
    Both _ _ -> withSynced $ do
        homeDirPath  <- getHomeDir
        case lPath of
            (File path) -> do
                filePath <- resolveFile homeDirPath path >>= makeRelative homeDirPath
                resolveConfiguration files removeFile filePath
            (Dir path)  -> do
                dirPath <- resolveDir homeDirPath path >>= makeRelative homeDirPath
                resolveConfiguration directories removeDirRecur dirPath

resolveConfiguration :: Lens' LifeConfiguration (Set (Path Rel t))
                     -> (Path Abs t -> IO ()) -- ^ function to remove object
                     -> Path Rel t
                     -> IO ()
resolveConfiguration confLens removeFun path = do
    configuration <- parseHomeLife

    let newConfiguration = configuration & confLens %~ Set.delete path
    if configuration == newConfiguration
    then warningMessage "File or directory is not in tracked" >> exitFailure
    else do
        writeGlobalLife newConfiguration
        removeFromRepo removeFun path