module Codec.Tiled.Layer.Data where

import Control.Applicative ((<|>))
import Data.Aeson (FromJSON(..), ToJSON(..), withArray, withText)
import Data.Text (Text)
import Data.Vector.Storable qualified as Storable
import GHC.Generics (Generic)

import Data.Tiled.GID (GID)

data LayerData
  = Base64 Text
  | GIDs (Storable.Vector GID)
  deriving (LayerData -> LayerData -> Bool
(LayerData -> LayerData -> Bool)
-> (LayerData -> LayerData -> Bool) -> Eq LayerData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LayerData -> LayerData -> Bool
$c/= :: LayerData -> LayerData -> Bool
== :: LayerData -> LayerData -> Bool
$c== :: LayerData -> LayerData -> Bool
Eq, Int -> LayerData -> ShowS
[LayerData] -> ShowS
LayerData -> String
(Int -> LayerData -> ShowS)
-> (LayerData -> String)
-> ([LayerData] -> ShowS)
-> Show LayerData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LayerData] -> ShowS
$cshowList :: [LayerData] -> ShowS
show :: LayerData -> String
$cshow :: LayerData -> String
showsPrec :: Int -> LayerData -> ShowS
$cshowsPrec :: Int -> LayerData -> ShowS
Show, (forall x. LayerData -> Rep LayerData x)
-> (forall x. Rep LayerData x -> LayerData) -> Generic LayerData
forall x. Rep LayerData x -> LayerData
forall x. LayerData -> Rep LayerData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep LayerData x -> LayerData
$cfrom :: forall x. LayerData -> Rep LayerData x
Generic)

instance FromJSON LayerData where
  parseJSON :: Value -> Parser LayerData
parseJSON Value
v = Value -> Parser LayerData
encoded Value
v Parser LayerData -> Parser LayerData -> Parser LayerData
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Value -> Parser LayerData
csv Value
v
    where
      encoded :: Value -> Parser LayerData
encoded =
        String -> (Text -> Parser LayerData) -> Value -> Parser LayerData
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"Base64" ((Text -> Parser LayerData) -> Value -> Parser LayerData)
-> (Text -> Parser LayerData) -> Value -> Parser LayerData
forall a b. (a -> b) -> a -> b
$
          LayerData -> Parser LayerData
forall (f :: * -> *) a. Applicative f => a -> f a
pure (LayerData -> Parser LayerData)
-> (Text -> LayerData) -> Text -> Parser LayerData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> LayerData
Base64

      csv :: Value -> Parser LayerData
csv =
        String -> (Array -> Parser LayerData) -> Value -> Parser LayerData
forall a. String -> (Array -> Parser a) -> Value -> Parser a
withArray String
"GIDs" ((Array -> Parser LayerData) -> Value -> Parser LayerData)
-> (Array -> Parser LayerData) -> Value -> Parser LayerData
forall a b. (a -> b) -> a -> b
$
          (Vector GID -> LayerData)
-> Parser (Vector GID) -> Parser LayerData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Vector GID -> LayerData
GIDs (Vector GID -> LayerData)
-> (Vector GID -> Vector GID) -> Vector GID -> LayerData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector GID -> Vector GID
forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
Storable.convert) (Parser (Vector GID) -> Parser LayerData)
-> (Array -> Parser (Vector GID)) -> Array -> Parser LayerData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Value -> Parser GID) -> Array -> Parser (Vector GID)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Value -> Parser GID
forall a. FromJSON a => Value -> Parser a
parseJSON

instance ToJSON LayerData where
  toJSON :: LayerData -> Value
toJSON = \case
    Base64 Text
text ->
      Text -> Value
forall a. ToJSON a => a -> Value
toJSON Text
text
    GIDs Vector GID
ints ->
      Vector GID -> Value
forall a. ToJSON a => a -> Value
toJSON Vector GID
ints