module Dingo.Internal.Base
       ( WidgetId
       , CallbackId
       , Command(..)
       , callbackIdParser
       , succCallbackId
       , succWidgetId
       , widgetIdParser
       , widgetIdToLazyText
       , zeroCallbackId
       , zeroWidgetId
       ) where

import           Data.Aeson (Value)
import           Data.Attoparsec (Parser)
import           Data.Attoparsec.Char8 (decimal)
import           Data.Hashable (Hashable(..))
import           Data.Text (Text)
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder.Int as TLBI
import           Dingo.Internal.EventTypes (Event(..))
import           Dingo.Selector
import           Text.Blaze (Html, ToValue(..))
import           Text.Julius (JavascriptUrl, ToJavascript(..))

-- | Widget ID.
newtype WidgetId = WidgetId Int
                 deriving (Show, Eq, Ord)

succWidgetId :: WidgetId -> WidgetId
succWidgetId (WidgetId i) = WidgetId (i+1)

zeroWidgetId :: WidgetId
zeroWidgetId = WidgetId 0

widgetIdParser :: Parser WidgetId
widgetIdParser = fmap WidgetId decimal

widgetIdToLazyText :: WidgetId -> TL.Text
widgetIdToLazyText (WidgetId i) = TL.pack $ show i

-- Widget IDs are hashable
instance Hashable WidgetId where
  hash (WidgetId i) = hash i

-- Callback ID.
newtype CallbackId = CallbackId Int
                     deriving (Show, Eq, Ord)

-- Find successor callback ID.
succCallbackId :: CallbackId -> CallbackId
succCallbackId (CallbackId i) = CallbackId (i+1)

zeroCallbackId :: CallbackId
zeroCallbackId = CallbackId 0

callbackIdParser :: Parser CallbackId
callbackIdParser = fmap CallbackId decimal

-- Command for the browser.
data Command = CallbackBySelector Event Selector CallbackId
             | SetWidgetValue WidgetId Value
             | SetTitle Text
             | AppendToWidgetChildren WidgetId Html
             | ReplaceWidgetChildren WidgetId Html
             | HeadMerge Html
             | AddEncoderDecoderFunctions WidgetId (JavascriptUrl Text) (JavascriptUrl Text)
             | TriggerEvent WidgetId Event
             | RawJavascript (JavascriptUrl Text)

-- Convert widget ID to attribute value. Used for generating HTML.
instance ToValue WidgetId where
  toValue (WidgetId widgetId) = toValue $ 'i' : show widgetId

-- | Convert widget ID to Javascript value. The converted value
-- is guaranteed to not contain any characters requiring quoting
-- or escaping in Javascript, nor to contain any non-ASCII characters.
instance ToJavascript WidgetId where
  toJavascript (WidgetId i) = TLBI.decimal i

-- | Convert callback ID to Javascript value. The converted value
-- is guaranteed to not contain any characters requiring quoting
-- or escaping in Javascript, nor to contain any non-ASCII characters.
instance ToJavascript CallbackId where
  toJavascript (CallbackId i) = TLBI.decimal i