{-# LANGUAGE UndecidableInstances #-}

module Bookhound.Format.Operations.ToXml (ToXml(..)) where

import Bookhound.Format.Operations.ToJson (ToJson (..))
import Bookhound.Format.SyntaxTrees.Json  (JsonExpression (..))
import Bookhound.Format.SyntaxTrees.Xml   (XmlExpression (..), literalExpression)

import           Data.Char (toLower)
import qualified Data.Map  as Map


class ToXml a where
  toXml :: a -> XmlExpression


instance {-# OVERLAPPABLE #-} ToJson a => ToXml a where
  toXml :: a -> XmlExpression
toXml = forall a. ToXml a => a -> XmlExpression
toXml forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJson a => a -> JsonExpression
toJson

instance ToXml XmlExpression where
  toXml :: XmlExpression -> XmlExpression
toXml = forall a. a -> a
id


instance ToXml JsonExpression where

  toXml :: JsonExpression -> XmlExpression
toXml = \case
    JsonExpression
JsNull       -> String -> XmlExpression
literalExpression String
"null"
    JsNumber Double
n   -> String -> XmlExpression
literalExpression forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show Double
n
    JsBool Bool
bool  -> String -> XmlExpression
literalExpression forall a b. (a -> b) -> a -> b
$ Char -> Char
toLower forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Show a => a -> String
show Bool
bool
    JsString String
str -> String -> XmlExpression
literalExpression String
str

    JsArray [JsonExpression]
arr  -> String -> Map String String -> [XmlExpression] -> XmlExpression
XmlExpression String
"array" forall k a. Map k a
Map.empty (forall a. ToXml a => a -> XmlExpression
elemExpr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [JsonExpression]
arr) where

      elemExpr :: a -> XmlExpression
elemExpr a
element = XmlExpression { $sel:tagName:XmlExpression :: String
tagName = String
"elem",
                                       $sel:fields:XmlExpression :: Map String String
fields = forall k a. Map k a
Map.empty,
                                       $sel:expressions:XmlExpression :: [XmlExpression]
expressions = [forall a. ToXml a => a -> XmlExpression
toXml a
element] }

    JsObject Map String JsonExpression
obj -> String -> Map String String -> [XmlExpression] -> XmlExpression
XmlExpression String
"object" forall k a. Map k a
Map.empty (forall {a}. ToXml a => (String, a) -> XmlExpression
keyValueExpr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall k a. Map k a -> [(k, a)]
Map.toList Map String JsonExpression
obj)  where

      keyValueExpr :: (String, a) -> XmlExpression
keyValueExpr (String
key, a
value) = XmlExpression { $sel:tagName:XmlExpression :: String
tagName = String
key,
                                                  $sel:fields:XmlExpression :: Map String String
fields = forall k a. Map k a
Map.empty,
                                                  $sel:expressions:XmlExpression :: [XmlExpression]
expressions = [forall a. ToXml a => a -> XmlExpression
toXml a
value] }