{-|
Module: BattlePlace.WebApi
Description: Web API definitions.
License: MIT
-}

{-# LANGUAGE DataKinds, DeriveGeneric, GeneralizedNewtypeDeriving, StandaloneDeriving, TemplateHaskell, TypeOperators #-}

module BattlePlace.WebApi
  ( WebApi
  , ClientAuthRequest(..)
  , ClientAuthResponse(..)
  , MatchRequest(..)
  , MatchResponse(..)
  , MatchStatusResponse(..)
  , SessionResultRequest(..)
  , ServerMatchRequest(..)
  , ServerMatchResponse(..)
  , ServerMatchCancelRequest(..)
  , ServerMatchCancelResponse(..)
  , ServerMatchSessionsRequest(..)
  , ServerMatchSessionsResponse(..)
  , ServerSessionResultRequest(..)
  ) where

import qualified Data.Text as T
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import Servant.API

import BattlePlace.Token.Types
import BattlePlace.Util
import BattlePlace.WebApi.Auth
import BattlePlace.WebApi.Types

type WebApi = "v1a" :>
  (    "client" :>
    (    "auth" :> ReqBody '[JSON] ClientAuthRequest :> Post '[JSON] ClientAuthResponse
    :<|> "match" :>
      (    AuthProtect ClientToken :> ReqBody '[JSON] MatchRequest :> Post '[JSON] MatchResponse
      :<|> AuthProtect ClientToken :> Capture "matchToken" (InternalToken MatchToken) :> Get '[JSON] MatchStatusResponse
      :<|> AuthProtect ClientToken :> Capture "matchToken" (InternalToken MatchToken) :> Delete '[JSON] ()
      )
    :<|> "session" :> Capture "sessionToken" (InternalToken SessionToken) :>
      (    "result" :> AuthProtect ClientToken :> ReqBody '[JSON] SessionResultRequest :> Post '[JSON] ()
      )
    :<|> "info" :>
      (    "stats" :> AuthProtect ClientToken :> Get '[JSON] UserStats
      )
    )
  :<|> "server" :>
    (    "match" :>
      (    ReqBody '[JSON] ServerMatchRequest :> Post '[JSON] ServerMatchResponse
      :<|> ReqBody '[JSON] ServerMatchCancelRequest :> Delete '[JSON] ServerMatchCancelResponse
      :<|> "sessions" :> ReqBody '[JSON] ServerMatchSessionsRequest :> Post '[JSON] ServerMatchSessionsResponse
      )
    :<|> "session" :> Capture "serverSessionToken" (InternalToken ServerSessionToken) :>
      (    "result" :> ReqBody '[JSON] ServerSessionResultRequest :> Post '[JSON] ()
      )
    )
  )

data ClientAuthRequest = ClientAuthRequest
  { clientAuthRequest_projectId :: {-# UNPACK #-} !ProjectId
  , clientAuthRequest_auth :: !Auth
  }

data ClientAuthResponse
  = ClientAuthResponse_authenticated
    { clientAuthResponse_clientToken :: !(InternalToken ClientToken)
    , clientAuthResponse_name :: !T.Text
    , clientAuthResponse_pictureUrl :: !T.Text
    }
  | ClientAuthResponse_notAuthenticated
    { clientAuthResponse_error :: !T.Text
    }

data MatchRequest = MatchRequest
  { matchRequest_teamSizes :: !(VU.Vector MatchTeamSize)
  , matchRequest_maxMatchTime :: {-# UNPACK #-} !Int
  , matchRequest_matchTag :: !(Maybe MatchTag)
  , matchRequest_serverTag :: !(Maybe ServerTag)
  , matchRequest_info :: !(Maybe MatchPlayerInfo)
  }

data MatchResponse = MatchResponse
  { matchResponse_matchToken :: !(InternalToken MatchToken)
  }

data MatchStatusResponse
  = MatchStatusResponse_notFound
  | MatchStatusResponse_inProgress
  | MatchStatusResponse_matched
    { matchStatusResponse_session :: !MatchSession
    }
  | MatchStatusResponse_failed
    { matchStatusResponse_reason :: !MatchFailureReason
    }

data SessionResultRequest
  = SessionResultRequest_finished
    { sessionResultRequest_ranks :: !(V.Vector Int)
    }
  | SessionResultRequest_cancelled

data ClientDataRequest = ClientDataRequest
  { clientDataRequest_after :: !(Maybe T.Text)
  }

data ServerMatchRequest = ServerMatchRequest
  { serverMatchRequest_projectId :: {-# UNPACK #-} !ProjectId
  , serverMatchRequest_projectServerToken :: !ProjectServerToken
  , serverMatchRequest_serverTag :: !(Maybe ServerTag)
  , serverMatchRequest_name :: !ProjectServerName
  , serverMatchRequest_info :: !(Maybe MatchServerInfo)
  , serverMatchRequest_timeout :: !(Maybe Int)
  }

data ServerMatchResponse
  = ServerMatchResponse_registered
  | ServerMatchResponse_unused

data ServerMatchCancelRequest = ServerMatchCancelRequest
  { serverMatchCancelRequest_projectId :: {-# UNPACK #-} !ProjectId
  , serverMatchCancelRequest_projectServerToken :: !ProjectServerToken
  , serverMatchCancelRequest_name :: !ProjectServerName
  }

data ServerMatchCancelResponse
  = ServerMatchCancelResponse_cancelled
  | ServerMatchCancelResponse_unused

data ServerMatchSessionsRequest = ServerMatchSessionsRequest
  { serverMatchSessionsRequest_projectId :: {-# UNPACK #-} !ProjectId
  , serverMatchSessionsRequest_projectServerToken :: !ProjectServerToken
  , serverMatchSessionsRequest_name :: !ProjectServerName
  }

data ServerMatchSessionsResponse = ServerMatchSessionsResponse
  { serverMatchSessionsResponse_sessions :: !(V.Vector MatchServerSession)
  }

data ServerSessionResultRequest
  = ServerSessionResultRequest_finished
    { serverSessionResultRequest_ranks :: !(V.Vector Int)
    }
  | ServerSessionResultRequest_cancelled

declareStruct
  [ ''ClientAuthRequest
  , ''ClientAuthResponse
  , ''MatchRequest
  , ''MatchResponse
  , ''MatchStatusResponse
  , ''SessionResultRequest
  , ''ClientDataRequest
  , ''ServerMatchRequest
  , ''ServerMatchResponse
  , ''ServerMatchCancelRequest
  , ''ServerMatchCancelResponse
  , ''ServerMatchSessionsRequest
  , ''ServerMatchSessionsResponse
  , ''ServerSessionResultRequest
  ]