{-# LANGUAGE OverloadedStrings #-}
module Language.PureScript.Ide.Error
       (ErrorMsg, PscIdeError(..), textError, first)
       where

import           Data.Aeson
import           Data.Monoid
import           Data.Text                     (Text, pack)
import           Language.PureScript.Ide.Types (ModuleIdent)
import qualified Text.Parsec.Error             as P

type ErrorMsg = String

data PscIdeError
    = GeneralError ErrorMsg
    | NotFound Text
    | ModuleNotFound ModuleIdent
    | ModuleFileNotFound ModuleIdent
    | ParseError P.ParseError ErrorMsg
    deriving (Show, Eq)

instance ToJSON PscIdeError where
  toJSON err = object
    [ "resultType" .= ("error" :: Text)
    , "result" .= textError err
    ]

textError :: PscIdeError -> Text
textError (GeneralError msg)          = pack msg
textError (NotFound ident)            = "Symbol '" <> ident <> "' not found."
textError (ModuleNotFound ident)      = "Module '" <> ident <> "' not found."
textError (ModuleFileNotFound ident)  = "Extern file for module " <> ident <>" could not be found"
textError (ParseError parseError msg) = pack $ msg <> ": " <> show (escape parseError)
  where
    -- escape newlines and other special chars so we can send the error over the socket as a single line
    escape :: P.ParseError -> String
    escape = show

-- | Specialized version of `first` from `Data.Bifunctors`
first :: (a -> b) -> Either a r -> Either b r
first f (Left x)   = Left (f x)
first _ (Right r2) = Right r2