module Bookhound.Format.SyntaxTrees.Toml (TomlExpression(..), TableType(..)) where

import Bookhound.Utils.DateTime (showDateTime)
import Bookhound.Utils.Foldable (stringify)
import Bookhound.Utils.Map      (showMap)

import Data.Char (toLower)
import Data.Time (Day, TimeOfDay, ZonedTime (..))

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



data TomlExpression
  = TomlInteger Integer
  | TomlFloat Double
  | TomlBool Bool
  | TomlString String
  | TomlDate Day
  | TomlTime TimeOfDay
  | TomlDateTime ZonedTime
  | TomlArray [TomlExpression]
  | TomlTable TableType (Map String TomlExpression)
  | TomlNull
  deriving (TomlExpression -> TomlExpression -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TomlExpression -> TomlExpression -> Bool
$c/= :: TomlExpression -> TomlExpression -> Bool
== :: TomlExpression -> TomlExpression -> Bool
$c== :: TomlExpression -> TomlExpression -> Bool
Eq, Eq TomlExpression
TomlExpression -> TomlExpression -> Bool
TomlExpression -> TomlExpression -> Ordering
TomlExpression -> TomlExpression -> TomlExpression
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TomlExpression -> TomlExpression -> TomlExpression
$cmin :: TomlExpression -> TomlExpression -> TomlExpression
max :: TomlExpression -> TomlExpression -> TomlExpression
$cmax :: TomlExpression -> TomlExpression -> TomlExpression
>= :: TomlExpression -> TomlExpression -> Bool
$c>= :: TomlExpression -> TomlExpression -> Bool
> :: TomlExpression -> TomlExpression -> Bool
$c> :: TomlExpression -> TomlExpression -> Bool
<= :: TomlExpression -> TomlExpression -> Bool
$c<= :: TomlExpression -> TomlExpression -> Bool
< :: TomlExpression -> TomlExpression -> Bool
$c< :: TomlExpression -> TomlExpression -> Bool
compare :: TomlExpression -> TomlExpression -> Ordering
$ccompare :: TomlExpression -> TomlExpression -> Ordering
Ord)


data TableType
  = TopLevel
  | Standard
  | Inline
  deriving (TableType -> TableType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TableType -> TableType -> Bool
$c/= :: TableType -> TableType -> Bool
== :: TableType -> TableType -> Bool
$c== :: TableType -> TableType -> Bool
Eq, Eq TableType
TableType -> TableType -> Bool
TableType -> TableType -> Ordering
TableType -> TableType -> TableType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TableType -> TableType -> TableType
$cmin :: TableType -> TableType -> TableType
max :: TableType -> TableType -> TableType
$cmax :: TableType -> TableType -> TableType
>= :: TableType -> TableType -> Bool
$c>= :: TableType -> TableType -> Bool
> :: TableType -> TableType -> Bool
$c> :: TableType -> TableType -> Bool
<= :: TableType -> TableType -> Bool
$c<= :: TableType -> TableType -> Bool
< :: TableType -> TableType -> Bool
$c< :: TableType -> TableType -> Bool
compare :: TableType -> TableType -> Ordering
$ccompare :: TableType -> TableType -> Ordering
Ord)


instance Show TomlExpression where
  show :: TomlExpression -> String
show = \case
    TomlExpression
TomlNull                   -> String
"null"
    TomlInteger Integer
n              -> forall a. Show a => a -> String
show Integer
n
    TomlFloat Double
n                -> forall a. Show a => a -> String
show Double
n
    TomlBool Bool
bool              -> Char -> Char
toLower forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Show a => a -> String
show Bool
bool
    TomlDate Day
date              -> forall a. Show a => a -> String
show Day
date
    TomlTime TimeOfDay
time              -> forall a. Show a => a -> String
show TimeOfDay
time
    TomlDateTime ZonedTime
dateTime      -> ZonedTime -> String
showDateTime ZonedTime
dateTime
    TomlString String
str             -> forall a. Show a => a -> String
show String
str

    TomlTable TableType
Standard Map String TomlExpression
table   -> forall (m :: * -> *).
Foldable m =>
String -> String -> String -> Int -> m String -> String
stringify String
"\n" String
"" String
"" Int
0 forall a b. (a -> b) -> a -> b
$ forall a.
String -> ShowS -> (a -> String) -> Map String a -> [String]
showMap String
" = " forall a. a -> a
id forall a. Show a => a -> String
show Map String TomlExpression
table

    TomlTable TableType
TopLevel Map String TomlExpression
table   -> forall (m :: * -> *).
Foldable m =>
String -> String -> String -> Int -> m String -> String
stringify String
"\n\n" String
"\n" String
"\n" Int
0 forall a b. (a -> b) -> a -> b
$ forall a.
String -> ShowS -> (a -> String) -> Map String a -> [String]
showMap String
"" ShowS
showTableHeader forall a. Show a => a -> String
show Map String TomlExpression
table where
      showTableHeader :: ShowS
showTableHeader String
header = if String
header forall a. Eq a => a -> a -> Bool
/= String
"" then String
"[" forall a. Semigroup a => a -> a -> a
<> String
header forall a. Semigroup a => a -> a -> a
<> String
"]" forall a. Semigroup a => a -> a -> a
<> String
"\n"  else String
""

    TomlTable TableType
Inline Map String TomlExpression
table     -> forall (m :: * -> *).
Foldable m =>
String -> String -> String -> Int -> m String -> String
stringify (String
", " forall a. Semigroup a => a -> a -> a
<> String
sep) (String
"{ " forall a. Semigroup a => a -> a -> a
<> String
sep) (String
" }" forall a. Semigroup a => a -> a -> a
<> String
sep) Int
n forall a b. (a -> b) -> a -> b
$
                                    forall a.
String -> ShowS -> (a -> String) -> Map String a -> [String]
showMap String
" = " forall a. a -> a
id forall a. Show a => a -> String
show Map String TomlExpression
table where
      (String
sep, Int
n) = if (forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat) (forall a. Show a => a -> String
show forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall k a. Map k a -> [(k, a)]
Map.toList Map String TomlExpression
table) forall a. Ord a => a -> a -> Bool
>= Int
80 then (String
"\n", Int
2) else (String
"", Int
0)

    TomlArray [TomlExpression]
arr              -> forall (m :: * -> *).
Foldable m =>
String -> String -> String -> Int -> m String -> String
stringify (String
", " forall a. Semigroup a => a -> a -> a
<> String
sep) (String
"[ " forall a. Semigroup a => a -> a -> a
<> String
sep) (String
" ]" forall a. Semigroup a => a -> a -> a
<> String
sep) Int
n forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> String
show forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TomlExpression]
arr where
      (String
sep, Int
n) = if (forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat) (forall a. Show a => a -> String
show forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TomlExpression]
arr) forall a. Ord a => a -> a -> Bool
>= Int
80 then (String
"\n", Int
2) else (String
"", Int
0)