// Copyright (C) Call of Nil contributors
// SPDX-License-Identifier: AGPL-3.0-only

use crate::app::App;
use crate::error::CoreError;
use crate::middleware::authorization::CurrentPlayer;
use crate::res;
use crate::response::{EitherExt, from_err};
use axum::extract::{Extension, Json, State};
use axum::response::Response;
use nil_payload::request::round::*;
use nil_payload::response::round::*;

pub async fn get(State(app): State<App>, Json(req): Json<GetRoundRequest>) -> Response {
  app
    .round(req.world, Clone::clone)
    .await
    .map_left(|round| res!(OK, GetRoundResponse(round)))
    .into_inner()
}

pub async fn set_ready(
  State(app): State<App>,
  Extension(player): Extension<CurrentPlayer>,
  Json(req): Json<SetPlayerReadyRequest>,
) -> Response {
  app
    .world_blocking_mut(req.world, move |world| {
      world.set_player_ready(&player, req.is_ready)?;
      Ok::<_, CoreError>(world.round().clone())
    })
    .await
    .try_map_left(|round| res!(OK, SetPlayerReadyResponse(round)))
    .into_inner()
}

pub async fn start(
  State(app): State<App>,
  Extension(player): Extension<CurrentPlayer>,
  Json(req): Json<StartRoundRequest>,
) -> Response {
  if app.server_kind().is_remote() {
    match app
      .database()
      .is_game_owned_by(req.world, player)
      .await
    {
      Ok(true) => {}
      Ok(false) => return res!(FORBIDDEN),
      Err(err) => return from_err(err),
    }
  }

  app
    .world_blocking_mut(req.world, move |world| {
      world.start_round()?;
      Ok::<_, CoreError>(world.round().clone())
    })
    .await
    .try_map_left(|round| res!(OK, StartRoundResponse(round)))
    .into_inner()
}
