{-| This module provides the default resolver for pre-defined components.
-}
module Data.Component.Resolver (
  resolver,
  foldResult,
) where

import Control.Monad
import Data.Aeson
import qualified Data.Text as T
import MiniLight
import qualified Data.Component.AnimationLayer as AnimationLayer
import qualified Data.Component.Button as Button
import qualified Data.Component.Layer as Layer
import qualified Data.Component.MessageEngine as MessageEngine
import qualified Data.Component.MessageLayer as MessageLayer
import qualified Data.Component.Selection as Selection

foldResult :: (String -> b) -> (a -> b) -> Result a -> b
foldResult f g r = case r of
  Error   err -> f err
  Success a   -> g a

resultM
  :: Result a
  -> (a -> MiniLight Component)
  -> MiniLight (Either String Component)
resultM r m = foldResult (return . Left) (fmap Right . m) r

-- | Pre-defined resolver supports all components in this library.
resolver :: Resolver
resolver name uid props = case name of
  "animation-layer" ->
    resultM (fromJSON props) $ newComponent uid <=< AnimationLayer.new
  "button" -> resultM (fromJSON props) $ newComponent uid <=< Button.new
  "layer"  -> resultM (fromJSON props) $ newComponent uid <=< Layer.new
  "message-engine" ->
    resultM (fromJSON props) $ newComponent uid <=< MessageEngine.new
  "message-layer" ->
    resultM (fromJSON props) $ newComponent uid <=< MessageLayer.new
  "tiled-layer" ->
    resultM (fromJSON props) $ newComponent uid <=< Layer.newNineTile
  "selection" -> resultM (fromJSON props) $ newComponent uid <=< Selection.new
  _           -> return $ Left $ "Unsupported component: " ++ T.unpack name