module Language.Haskell.Format.Types
  ( HaskellSource(..)
  , Reformatted(..)
  , Formatter(..)
  , Suggestion(..)
  ) where

import Control.Monad
import Data.Semigroup (Semigroup, (<>))

type ErrorString = String

data HaskellSource =
  HaskellSource FilePath
                String
  deriving (Eq)

newtype Suggestion =
  Suggestion String

instance Show Suggestion where
  show (Suggestion text) = text

data Reformatted = Reformatted
  { reformattedSource :: HaskellSource
  , suggestions       :: [Suggestion]
  }

instance Semigroup Reformatted where
  (Reformatted _ suggestionsA) <> (Reformatted sourceB suggestionsB) =
    Reformatted sourceB (suggestionsA <> suggestionsB)

instance Monoid Reformatted where
  mempty = Reformatted undefined []
  mappend = (<>)

newtype Formatter = Formatter
  { unFormatter :: HaskellSource -> Either ErrorString Reformatted
  }

instance Semigroup Formatter where
  (Formatter f) <> (Formatter g) = Formatter (asReformatter g <=< f)

instance Monoid Formatter where
  mempty = Formatter (\source -> Right (Reformatted source []))
  mappend = (<>)

asReformatter ::
     (HaskellSource -> Either ErrorString Reformatted)
  -> Reformatted
  -> Either ErrorString Reformatted
asReformatter formatter r = (r <>) <$> formatter (reformattedSource r)