# OPTIONS_GHC -Wno - orphans #
{-# LANGUAGE DataKinds             #-}
# LANGUAGE MultiParamTypeClasses #
# LANGUAGE PolyKinds              #
# LANGUAGE TypeFamilies           #
{-# LANGUAGE TypeOperators         #-}
module Network.Tox.App (app) where

import           Control.Monad             ((>=>))
import           Control.Monad.IO.Class    (liftIO)
import qualified Data.Binary               as Binary
import           Data.ByteString.Lazy      (ByteString)
import           Data.Maybe                (fromMaybe)
import qualified Data.MessagePack          as MessagePack
import           Servant
import           Test.QuickCheck.Arbitrary (arbitrary)
import qualified Test.QuickCheck.Gen       as Gen
import           Text.Groom                (groom)
import           Text.Read                 (readEither)

import           Network.Tox.SaveData      (SaveData)


instance MimeRender OctetStream SaveData where
    mimeRender p = mimeRender p . Binary.encode

instance MimeUnrender OctetStream SaveData where
    mimeUnrender _ bytes =
        case Binary.decodeOrFail bytes of
          Left (_, _, err) -> Left err
          Right (_, _, ok) -> Right ok

instance MimeRender PlainText SaveData where
    mimeRender p = mimeRender p . groom

instance MimeUnrender PlainText SaveData where
    mimeUnrender p = mimeUnrender p >=> readEither


-- API specification
type ToxcoreApi =
       -- Link to the source code repository, to comply with AGPL.
       "source" :> Get '[PlainText] String
  Get a random binary savedata .
  :<|> "random" :> QueryParam "size" Int :> Get '[OctetStream] SaveData
  Parse a binary string as savedata and output in human - readable form .
  :<|> "parse" :> ReqBody '[OctetStream] SaveData :> Post '[PlainText] SaveData
  Serialise a human readable  back to binary .
  :<|> "to-save" :> ReqBody '[PlainText] SaveData :> Post '[OctetStream] SaveData
  Serialise a human readable  to msgpack .
  :<|> "to-msgpack" :> ReqBody '[PlainText] SaveData :> Post '[OctetStream] ByteString

toxcoreApi :: Proxy ToxcoreApi
toxcoreApi = Proxy

-- Server-side handlers.
--
  There 's one handler per endpoint , which , just like in the type
-- that represents the API, are glued together using :<|>.
--
-- Each handler runs in the 'Handler' monad.
server :: Server ToxcoreApi
server =
         sourceH
    :<|> randomH
    :<|> parseH
    :<|> toSaveH
    :<|> toMsgpackH
  where
    sourceH = return "-toxcore\n"

    randomH size = liftIO $ Gen.generate $ Gen.resize (fromMaybe 30 size) arbitrary
    parseH = return
    toSaveH = return
    toMsgpackH = return . MessagePack.pack

  Turn the server into a WAI app . ' serve ' is provided by servant ,
-- more precisely by the Servant.Server module.
app :: Application
app = serve toxcoreApi server

# LANGUAGE DataKinds             #
# LANGUAGE TypeOperators         #
 API specification
 Link to the source code repository, to comply with AGPL.
 Server-side handlers.

 that represents the API, are glued together using :<|>.

 Each handler runs in the 'Handler' monad.
 more precisely by the Servant.Server module.
# OPTIONS_GHC -Wno - orphans #
# LANGUAGE MultiParamTypeClasses #
# LANGUAGE PolyKinds              #
# LANGUAGE TypeFamilies           #
module Network.Tox.App (app) where

import           Control.Monad             ((>=>))
import           Control.Monad.IO.Class    (liftIO)
import qualified Data.Binary               as Binary
import           Data.ByteString.Lazy      (ByteString)
import           Data.Maybe                (fromMaybe)
import qualified Data.MessagePack          as MessagePack
import           Servant
import           Test.QuickCheck.Arbitrary (arbitrary)
import qualified Test.QuickCheck.Gen       as Gen
import           Text.Groom                (groom)
import           Text.Read                 (readEither)

import           Network.Tox.SaveData      (SaveData)


instance MimeRender OctetStream SaveData where
    mimeRender p = mimeRender p . Binary.encode

instance MimeUnrender OctetStream SaveData where
    mimeUnrender _ bytes =
        case Binary.decodeOrFail bytes of
          Left (_, _, err) -> Left err
          Right (_, _, ok) -> Right ok

instance MimeRender PlainText SaveData where
    mimeRender p = mimeRender p . groom

instance MimeUnrender PlainText SaveData where
    mimeUnrender p = mimeUnrender p >=> readEither


type ToxcoreApi =
       "source" :> Get '[PlainText] String
  Get a random binary savedata .
  :<|> "random" :> QueryParam "size" Int :> Get '[OctetStream] SaveData
  Parse a binary string as savedata and output in human - readable form .
  :<|> "parse" :> ReqBody '[OctetStream] SaveData :> Post '[PlainText] SaveData
  Serialise a human readable  back to binary .
  :<|> "to-save" :> ReqBody '[PlainText] SaveData :> Post '[OctetStream] SaveData
  Serialise a human readable  to msgpack .
  :<|> "to-msgpack" :> ReqBody '[PlainText] SaveData :> Post '[OctetStream] ByteString

toxcoreApi :: Proxy ToxcoreApi
toxcoreApi = Proxy

  There 's one handler per endpoint , which , just like in the type
server :: Server ToxcoreApi
server =
         sourceH
    :<|> randomH
    :<|> parseH
    :<|> toSaveH
    :<|> toMsgpackH
  where
    sourceH = return "-toxcore\n"

    randomH size = liftIO $ Gen.generate $ Gen.resize (fromMaybe 30 size) arbitrary
    parseH = return
    toSaveH = return
    toMsgpackH = return . MessagePack.pack

  Turn the server into a WAI app . ' serve ' is provided by servant ,
app :: Application
app = serve toxcoreApi server
