module InterfaceSerialization ( loadInterface
                              , interfaceDecode
                              , validVersion
                              ) where

import qualified Data.ByteString.Lazy as L
import qualified Data.Binary as Binary

import qualified Elm.Internal.Version as Version
import System.Directory (doesFileExist)
import System.IO (hPutStrLn, stderr)
import System.Exit (exitFailure)

import SourceSyntax.Module

loadInterface :: FilePath -> IO (Either String L.ByteString)
loadInterface filePath = do
  exists <- doesFileExist filePath
  if exists
    then do
      byteString <- L.readFile filePath
      return $ Right byteString

    else
      return $ Left $ "Unable to find file " ++ filePath ++
                      " for deserialization!"

interfaceDecode :: Binary.Binary a =>
                   FilePath -> L.ByteString -> Either String a
interfaceDecode filePath bytes = do
  case Binary.decodeOrFail bytes of
    Right (_, _, binaryInfo) -> Right binaryInfo

    Left (_, offset, err) ->
        Left $ concat [ "Error reading build artifact: ", filePath, "\n"
                      , "    The exact error was '", err, "' at offset ", show offset, ".\n"
                      , "    The file was generated by a previous build and may be outdated or corrupt.\n"
                      , "    Please remove the file and try again."
                      ]

validVersion :: FilePath -> (String, ModuleInterface) ->
                Either String (String, ModuleInterface)
validVersion filePath (name, interface) =
    if iVersion interface == Version.elmVersion then
        Right (name, interface)
    else
        Left $ concat
               [ "Error reading build artifact: ", filePath, "\n"
               , "    It was generated by a different version of the compiler: "
               , show (iVersion interface), "\n"
               , "    Please remove the file and try again.\n"
               ]