{-# LANGUAGE DeriveGeneric #-}

module Battlesnake.Core.Coordinate where

import Data.Aeson
  ( FromJSON (parseJSON),
    KeyValue ((.=)),
    ToJSON (toEncoding),
    pairs,
    withObject,
    (.:),
  )
import GHC.Generics

-- | Represents a coordinate on the game board.
data Coordinate = Coordinate
  { Coordinate -> Integer
coordX :: Integer, -- ^ The X coordinate (0 indexed, from left to right)
    Coordinate -> Integer
coordY :: Integer -- ^ The Y coordinate (0 indexed, from bottom to top)
  }
  deriving (Int -> Coordinate -> ShowS
[Coordinate] -> ShowS
Coordinate -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Coordinate] -> ShowS
$cshowList :: [Coordinate] -> ShowS
show :: Coordinate -> String
$cshow :: Coordinate -> String
showsPrec :: Int -> Coordinate -> ShowS
$cshowsPrec :: Int -> Coordinate -> ShowS
Show, Coordinate -> Coordinate -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Coordinate -> Coordinate -> Bool
$c/= :: Coordinate -> Coordinate -> Bool
== :: Coordinate -> Coordinate -> Bool
$c== :: Coordinate -> Coordinate -> Bool
Eq, forall x. Rep Coordinate x -> Coordinate
forall x. Coordinate -> Rep Coordinate x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Coordinate x -> Coordinate
$cfrom :: forall x. Coordinate -> Rep Coordinate x
Generic)

instance ToJSON Coordinate where
  toEncoding :: Coordinate -> Encoding
toEncoding (Coordinate Integer
x Integer
y) = Series -> Encoding
pairs (Key
"x" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Integer
x forall a. Semigroup a => a -> a -> a
<> Key
"y" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Integer
y)

instance FromJSON Coordinate where
  parseJSON :: Value -> Parser Coordinate
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Coordinate" forall a b. (a -> b) -> a -> b
$ \Object
v -> Integer -> Integer -> Coordinate
Coordinate forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"x" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"y"