module Unused.TagsSource
    ( TagSearchOutcome(..)
    , loadTagsFromFile
    , loadTagsFromPipe
    ) where

import qualified Control.Exception as E
import qualified Data.Bifunctor as BF
import qualified Data.List as L
import qualified Data.Text as T
import qualified System.Directory as D
import           Unused.Util (safeReadFile)

data TagSearchOutcome
    = TagsFileNotFound [String]
    | IOError E.IOException

loadTagsFromPipe :: IO (Either TagSearchOutcome [String])
loadTagsFromPipe = fmap (Right . tokensFromTags) getContents

loadTagsFromFile :: IO (Either TagSearchOutcome [String])
loadTagsFromFile = fmap (fmap tokensFromTags) tagsContent

tokensFromTags :: String -> [String]
tokensFromTags =
    filter validTokens . L.nub . tokenLocations
  where
    tokenLocations = map (token . T.splitOn "\t" . T.pack) . lines
    token = T.unpack . head

validTokens :: String -> Bool
validTokens = not . L.isPrefixOf "!_TAG"

tagsContent :: IO (Either TagSearchOutcome String)
tagsContent = D.findFile possibleTagsFileDirectories "tags" >>= eitherReadFile

eitherReadFile :: Maybe String -> IO (Either TagSearchOutcome String)
eitherReadFile Nothing = return $ Left $ TagsFileNotFound possibleTagsFileDirectories
eitherReadFile (Just path) = BF.first IOError <$> safeReadFile path

possibleTagsFileDirectories :: [String]
possibleTagsFileDirectories = [".git", "tmp", "."]