-- |
-- Module:      Data.Karver.Types
-- Copyright:   Jeremy Hull 2013
-- License:     BSD3
--
-- Maintainer:  Jeremy Hull <sourdrums@gmail.com>
-- Stability:   experimental
-- Portability: unknown
--
-- Base types used throughout Karver.

module Text.Karver.Types
( Tokens(..)
, Value(..)
) where

import Control.Applicative ((<$>))
import qualified Data.Aeson as A
import Data.Text (Text)
import Data.HashMap.Strict
import Data.Vector

-- | When dealing with the syntax of karver, we first translate the given
-- 'Text' in 'Tokens' for easier manipulation. Each 'Tokens' type is
-- a representation of a certain type of data.
data Tokens = LiteralTok   Text
            -- ^ Literal token. This is the default 'Tokens' that gets
            --   matched only if it isn't any of the others.
            | IdentityTok  Text
            -- ^ Identity token. This is for a regular variable with no
            --   sign of it being an object or list. eg. {{ ident }}
            | ObjectTok    Text Text
            -- ^ Object token. This is similar to 'IdentityTok', but if
            --   there is a dot, it gets placed in the second value. The
            --   first 'Text' is the object name, while the second 'Text'
            --   is the key to the object. eg. {{ ident.key }}
            | ListTok      Text Int
            -- ^ List token. This is also similar to the 'IdentityTok', but
            --   if there is an opening square bracket, it gets place in
            --   the second value. 'Text' is the list name, while 'Int' is
            --   the index. eg {{ ident[4] }}
            | ConditionTok Text Text Text
            -- ^ If statement token. The first 'Text' will be the check if
            --   a identity is available or not. Second 'Text' is the body
            --   of the if statement. And the third 'Text' is the else body
            --   — if their isn't one, it will be empty.
            | LoopTok      Text Text Text
            -- ^ For loop token. The first 'Text' is the list that will be
            --   iterated over. Second 'Text' is the variable name a single
            --   element of the list will be placed into. Third 'Text' is
            --   the body of the loop that will be repeatedly translated
            --   from.
            | IncludeTok   Text
            -- ^ Include token. The 'Text' value store a file name, which
            --   includes its relative path, based on the current working
            --   directory.
            deriving (Show, Eq)

-- | Fairly basic work around for using different types inside a 'HashMap'.
-- The 'Value' type also make it possible for 'List' to contain more than
-- one type.
data Value = Literal Text
           -- ^ The base value for the storing of variable.
           | Object (HashMap Text Text)
           -- ^ An alias for 'HashMap', that will only hold 'Text' with
           --   'Text' as a key as well.
           | List   (Vector Value)
           -- ^ An alias for 'Vector', that can hold all three 'Value's
           --   — which isn't desirable, because their can be nested
           --   'List's.
           deriving (Show)

instance A.FromJSON Value where
  parseJSON o@(A.Object _) = Object <$> A.parseJSON o
  parseJSON a@(A.Array _)  = List <$> A.parseJSON a
  parseJSON v              = Literal <$> A.parseJSON v
  {-# INLINE parseJSON #-}