module Bio.MAE.Type
  ( Mae (..)
  , Block (..)
  , Table (..)
  , MaeValue (..)
  , FromMaeValue (..)
  ) where

import           Data.Map.Strict (Map)
import           Data.Maybe      (fromJust)
import           Data.Text       (Text)
import qualified Data.Text       as T (head, null, dropAround)

data Mae = Mae { Mae -> Text
version :: Text
               , Mae -> [Block]
blocks  :: [Block]
               }
  deriving (Mae -> Mae -> Bool
(Mae -> Mae -> Bool) -> (Mae -> Mae -> Bool) -> Eq Mae
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Mae -> Mae -> Bool
$c/= :: Mae -> Mae -> Bool
== :: Mae -> Mae -> Bool
$c== :: Mae -> Mae -> Bool
Eq, Int -> Mae -> ShowS
[Mae] -> ShowS
Mae -> String
(Int -> Mae -> ShowS)
-> (Mae -> String) -> ([Mae] -> ShowS) -> Show Mae
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Mae] -> ShowS
$cshowList :: [Mae] -> ShowS
show :: Mae -> String
$cshow :: Mae -> String
showsPrec :: Int -> Mae -> ShowS
$cshowsPrec :: Int -> Mae -> ShowS
Show)

data Block = Block { Block -> Text
blockName :: Text
                   , Block -> Map Text MaeValue
fields    :: Map Text MaeValue
                   , Block -> [Table]
tables    :: [Table]
                   }
  deriving (Block -> Block -> Bool
(Block -> Block -> Bool) -> (Block -> Block -> Bool) -> Eq Block
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Block -> Block -> Bool
$c/= :: Block -> Block -> Bool
== :: Block -> Block -> Bool
$c== :: Block -> Block -> Bool
Eq, Int -> Block -> ShowS
[Block] -> ShowS
Block -> String
(Int -> Block -> ShowS)
-> (Block -> String) -> ([Block] -> ShowS) -> Show Block
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Block] -> ShowS
$cshowList :: [Block] -> ShowS
show :: Block -> String
$cshow :: Block -> String
showsPrec :: Int -> Block -> ShowS
$cshowsPrec :: Int -> Block -> ShowS
Show)

data Table = Table { Table -> Text
tableName :: Text
                   , Table -> Map Text [MaeValue]
contents  :: Map Text [MaeValue]
                   }
  deriving (Table -> Table -> Bool
(Table -> Table -> Bool) -> (Table -> Table -> Bool) -> Eq Table
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Table -> Table -> Bool
$c/= :: Table -> Table -> Bool
== :: Table -> Table -> Bool
$c== :: Table -> Table -> Bool
Eq, Int -> Table -> ShowS
[Table] -> ShowS
Table -> String
(Int -> Table -> ShowS)
-> (Table -> String) -> ([Table] -> ShowS) -> Show Table
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Table] -> ShowS
$cshowList :: [Table] -> ShowS
show :: Table -> String
$cshow :: Table -> String
showsPrec :: Int -> Table -> ShowS
$cshowsPrec :: Int -> Table -> ShowS
Show)                   

data MaeValue = IntMaeValue Int
              | RealMaeValue Float
              | StringMaeValue Text
              | BoolMaeValue Bool
              | Absent
  deriving (MaeValue -> MaeValue -> Bool
(MaeValue -> MaeValue -> Bool)
-> (MaeValue -> MaeValue -> Bool) -> Eq MaeValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MaeValue -> MaeValue -> Bool
$c/= :: MaeValue -> MaeValue -> Bool
== :: MaeValue -> MaeValue -> Bool
$c== :: MaeValue -> MaeValue -> Bool
Eq, Int -> MaeValue -> ShowS
[MaeValue] -> ShowS
MaeValue -> String
(Int -> MaeValue -> ShowS)
-> (MaeValue -> String) -> ([MaeValue] -> ShowS) -> Show MaeValue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MaeValue] -> ShowS
$cshowList :: [MaeValue] -> ShowS
show :: MaeValue -> String
$cshow :: MaeValue -> String
showsPrec :: Int -> MaeValue -> ShowS
$cshowsPrec :: Int -> MaeValue -> ShowS
Show)

class FromMaeValue a where
    fromMaeValue :: MaeValue -> Maybe a

    unsafeFromMaeValue :: MaeValue -> a
    unsafeFromMaeValue = Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe a -> a) -> (MaeValue -> Maybe a) -> MaeValue -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MaeValue -> Maybe a
forall a. FromMaeValue a => MaeValue -> Maybe a
fromMaeValue

instance FromMaeValue Int where
    fromMaeValue :: MaeValue -> Maybe Int
    fromMaeValue :: MaeValue -> Maybe Int
fromMaeValue (IntMaeValue Int
i) = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
i
    fromMaeValue MaeValue
_               = Maybe Int
forall a. Maybe a
Nothing

instance FromMaeValue Float where
    fromMaeValue :: MaeValue -> Maybe Float
    fromMaeValue :: MaeValue -> Maybe Float
fromMaeValue (RealMaeValue Float
f) = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
f
    fromMaeValue MaeValue
_                = Maybe Float
forall a. Maybe a
Nothing

instance FromMaeValue Bool where
    fromMaeValue :: MaeValue -> Maybe Bool
    fromMaeValue :: MaeValue -> Maybe Bool
fromMaeValue (BoolMaeValue Bool
b) = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
b
    fromMaeValue MaeValue
_                = Maybe Bool
forall a. Maybe a
Nothing

instance FromMaeValue Text where
    fromMaeValue :: MaeValue -> Maybe Text
    fromMaeValue :: MaeValue -> Maybe Text
fromMaeValue (StringMaeValue Text
t) = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
    fromMaeValue MaeValue
_                  = Maybe Text
forall a. Maybe a
Nothing

instance FromMaeValue Char where
    fromMaeValue :: MaeValue -> Maybe Char
    fromMaeValue :: MaeValue -> Maybe Char
fromMaeValue (StringMaeValue Text
t) = Char -> Maybe Char
forall a. a -> Maybe a
Just (Char -> Maybe Char) -> Char -> Maybe Char
forall a b. (a -> b) -> a -> b
$ if Text -> Bool
T.null Text
t then Char
' ' else Text -> Char
T.head (Text -> Char) -> Text -> Char
forall a b. (a -> b) -> a -> b
$ Text -> Text
stripQuotes Text
t
    fromMaeValue MaeValue
_                  = Maybe Char
forall a. Maybe a
Nothing
         
stripQuotes :: Text -> Text
stripQuotes :: Text -> Text
stripQuotes = (Char -> Bool) -> Text -> Text
T.dropAround (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'"')