{-# LANGUAGE CPP             #-}
{-# LANGUAGE TemplateHaskell #-}

module Development.IDE.Graph.Internal.Paths (readDataFileHTML) where

#ifndef FILE_EMBED
import           Control.Exception    (SomeException (SomeException), catch)
import           Control.Monad        (filterM)
import           Paths_hls_graph
import           System.Directory     (doesFileExist, getCurrentDirectory)
import           System.Environment   (getExecutablePath)
import           System.FilePath      (takeDirectory, (</>))
import           System.IO.Unsafe     (unsafePerformIO)
#endif
import qualified Data.ByteString.Lazy as LBS

#ifdef FILE_EMBED
import qualified Data.ByteString      as BS
import           Data.FileEmbed

htmlDataFiles :: [(FilePath, BS.ByteString)]
htmlDataFiles =
  [
#ifdef __GHCIDE__
    ("profile.html",  $(embedFile "hls-graph/html/profile.html"))
  , ("shake.js",      $(embedFile "hls-graph/html/shake.js"))
#else
    ("profile.html",  $(embedFile "html/profile.html"))
  , ("shake.js",      $(embedFile "html/shake.js"))
#endif
  ]

readDataFileHTML :: FilePath -> IO LBS.ByteString
readDataFileHTML file = do
    case lookup file htmlDataFiles of
      Nothing -> fail $ "Could not find data file " ++ file ++ " in embedded data files!"
      Just x  -> pure (LBS.fromStrict x)

#else
-- We want getDataFileName to be relative to the current directory on program startup,
-- even if we issue a change directory command. Therefore, first call caches, future ones read.

{-# NOINLINE dataDirs #-}
dataDirs :: [String]
dataDirs = unsafePerformIO $ do
    datdir <- getDataDir
    exedir <- takeDirectory <$> getExecutablePath `catch` \SomeException{} -> pure ""
    curdir <- getCurrentDirectory
    pure $ [datdir] ++ [exedir | exedir /= ""] ++ [curdir]


getDataFile :: FilePath -> IO FilePath
getDataFile file = do
    let poss = map (</> file) dataDirs
    res <- filterM doesFileExist poss
    case res of
        [] -> fail $ unlines $ ("Could not find data file " ++ file ++ ", looked in:") : map ("  " ++) poss
        x:_ -> pure x

readDataFileHTML :: FilePath -> IO LBS.ByteString
readDataFileHTML file = LBS.readFile =<< getDataFile ("html" </> file)

#endif
