{-# LANGUAGE OverloadedStrings #-}
module Periodic.Types.ServerCommand
  ( ServerCommand (..)
  , isSuccess
  , isPong
  ) where

import           Periodic.Types.Internal
import           Periodic.Types.Job      (Job)

import           Data.Binary
import           Data.Binary.Get         (getRemainingLazyByteString,
                                          getWord32be)
import           Data.Binary.Put         (putByteString, putWord32be)
import           Data.ByteString         (ByteString)
import           Data.ByteString.Lazy    (toStrict)

data ServerCommand = Noop
    | JobAssign Job
    | NoJob
    | Pong
    | Unknown
    | Success
    | Config Int
    | Acquired Bool
    | NoWorker
    | Data ByteString
    deriving (Int -> ServerCommand -> ShowS
[ServerCommand] -> ShowS
ServerCommand -> String
(Int -> ServerCommand -> ShowS)
-> (ServerCommand -> String)
-> ([ServerCommand] -> ShowS)
-> Show ServerCommand
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ServerCommand] -> ShowS
$cshowList :: [ServerCommand] -> ShowS
show :: ServerCommand -> String
$cshow :: ServerCommand -> String
showsPrec :: Int -> ServerCommand -> ShowS
$cshowsPrec :: Int -> ServerCommand -> ShowS
Show)

instance Binary ServerCommand where
  get :: Get ServerCommand
get = do
    Word8
tp <- Get Word8
getWord8
    case Word8
tp of
      0 -> ServerCommand -> Get ServerCommand
forall (f :: * -> *) a. Applicative f => a -> f a
pure ServerCommand
Noop
      5 -> Job -> ServerCommand
JobAssign (Job -> ServerCommand) -> Get Job -> Get ServerCommand
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Job
forall t. Binary t => Get t
get
      6 -> ServerCommand -> Get ServerCommand
forall (f :: * -> *) a. Applicative f => a -> f a
pure ServerCommand
NoJob
      10 -> ServerCommand -> Get ServerCommand
forall (f :: * -> *) a. Applicative f => a -> f a
pure ServerCommand
Pong
      12 -> ServerCommand -> Get ServerCommand
forall (f :: * -> *) a. Applicative f => a -> f a
pure ServerCommand
Unknown
      16 -> ServerCommand -> Get ServerCommand
forall (f :: * -> *) a. Applicative f => a -> f a
pure ServerCommand
Success
      24 -> do
        Word32
val <- Get Word32
getWord32be
        ServerCommand -> Get ServerCommand
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ServerCommand -> Get ServerCommand)
-> (Int -> ServerCommand) -> Int -> Get ServerCommand
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ServerCommand
Config (Int -> Get ServerCommand) -> Int -> Get ServerCommand
forall a b. (a -> b) -> a -> b
$ Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
val
      26 -> do
        Word8
v <- Get Word8
getWord8
        ServerCommand -> Get ServerCommand
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ServerCommand -> Get ServerCommand)
-> ServerCommand -> Get ServerCommand
forall a b. (a -> b) -> a -> b
$ Bool -> ServerCommand
Acquired (Bool -> ServerCommand) -> Bool -> ServerCommand
forall a b. (a -> b) -> a -> b
$ Word8
v Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== 1
      29 -> ServerCommand -> Get ServerCommand
forall (f :: * -> *) a. Applicative f => a -> f a
pure ServerCommand
NoWorker
      30 -> ByteString -> ServerCommand
Data (ByteString -> ServerCommand)
-> (ByteString -> ByteString) -> ByteString -> ServerCommand
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
toStrict (ByteString -> ServerCommand)
-> Get ByteString -> Get ServerCommand
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get ByteString
getRemainingLazyByteString
      _  -> String -> Get ServerCommand
forall a. HasCallStack => String -> a
error (String -> Get ServerCommand) -> String -> Get ServerCommand
forall a b. (a -> b) -> a -> b
$ "Error ServerCommand" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word8 -> String
forall a. Show a => a -> String
show Word8
tp

  put :: ServerCommand -> Put
put Noop            = Word8 -> Put
putWord8 0
  put (JobAssign job :: Job
job) = do
    Word8 -> Put
putWord8 5
    Job -> Put
forall t. Binary t => t -> Put
put Job
job
  put NoJob           = Word8 -> Put
putWord8 6
  put Pong            = Word8 -> Put
putWord8 10
  put Unknown         = Word8 -> Put
putWord8 12
  put Success         = Word8 -> Put
putWord8 16
  put (Config v :: Int
v)      = do
    Word8 -> Put
putWord8 24
    Word32 -> Put
putWord32be (Word32 -> Put) -> Word32 -> Put
forall a b. (a -> b) -> a -> b
$ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
v
  put (Acquired True)    = do
    Word8 -> Put
putWord8 26
    Word8 -> Put
putWord8 1
  put (Acquired False)    = do
    Word8 -> Put
putWord8 26
    Word8 -> Put
putWord8 0
  put NoWorker            = Word8 -> Put
putWord8 29
  put (Data bs :: ByteString
bs)           = do
    Word8 -> Put
putWord8 30
    ByteString -> Put
putByteString ByteString
bs

instance Validatable ServerCommand where
  validate :: ServerCommand -> Either String ()
validate (JobAssign job :: Job
job) = Job -> Either String ()
forall a. Validatable a => a -> Either String ()
validate Job
job
  validate (Config v :: Int
v)      = String -> Int -> Int -> Int -> Either String ()
forall a. Ord a => String -> a -> a -> a -> Either String ()
validateNum "ConfigValue" 0 0xFFFFFFFF Int
v
  validate _               = () -> Either String ()
forall a b. b -> Either a b
Right ()


isSuccess :: ServerCommand -> Bool
isSuccess :: ServerCommand -> Bool
isSuccess Success = Bool
True
isSuccess _       = Bool
False

isPong :: ServerCommand -> Bool
isPong :: ServerCommand -> Bool
isPong Pong = Bool
True
isPong _    = Bool
False