{-# LANGUAGE OverloadedStrings, DeriveGeneric, DeriveAnyClass #-}
module Data.Comic.Types (
   ImageName
 , Font(..), FontName, FontSize, HintSize
 , RGBA, blackRGBA, whiteRGBA
 , Position (..), RelPosition (..)
 ) where

import Control.DeepSeq
import Control.Monad
import qualified Data.Aeson as JS
import Data.Aeson (ToJSON(..), FromJSON(..), (.:))
import Data.Hashable (Hashable(hashWithSalt))
import Data.Text (Text)
import Data.Word
import GHC.Generics (Generic)

type ImageName = Text
type FontName = Text
type FontSize = Int
type HintSize = Int
type RGBA = (Word8, Word8, Word8, Word8)

blackRGBA :: RGBA
blackRGBA = (0, 0, 0, 255)

whiteRGBA :: RGBA
whiteRGBA = (255, 255, 255, 255)

data Font =
    Font {-# UNPACK #-} !FontName {-# UNPACK #-} !FontSize {-# UNPACK #-} !RGBA
  deriving (Read, Show, Eq, Ord, Generic, NFData)

instance Hashable Font where
  hashWithSalt s (Font fn fs rgba) =
    hashWithSalt s (fn, fs, rgba)

data Position =
    Pos { _pX :: {-# UNPACK #-} !Int, _pY :: {-# UNPACK #-} !Int }
  deriving (Read, Show, Eq, Ord, Generic, NFData)

instance Hashable Position where
  hashWithSalt s (Pos x y) = hashWithSalt s (x, y)

instance ToJSON Position where
  toJSON (Pos x y) = JS.object [("x", toJSON x), ("y", toJSON y)]

instance FromJSON Position where
  parseJSON (JS.Object v) = Pos <$> v .: "x" <*> v .: "y"
  parseJSON _ = mzero

data RelPosition =
    RPos { _rX :: {-# UNPACK #-} !Float, _rY :: {-# UNPACK #-} !Float }
  deriving (Read, Show, Eq, Ord, Generic, NFData)

instance Hashable RelPosition where
  hashWithSalt s (RPos x y) = hashWithSalt s (x, y)

instance ToJSON RelPosition where
  toJSON (RPos x y) = JS.object [("x", toJSON x), ("y", toJSON y)]

instance FromJSON RelPosition where
  parseJSON (JS.Object v) = RPos <$> v .: "x" <*> v .: "y"
  parseJSON _ = mzero