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

use crate::error::{Error, Result};
use crate::event::Emitter;
use crate::savedata::Savedata;
use crate::world::World;
use std::sync::Arc;

impl World {
  pub(super) fn consume_pending_save(&mut self) -> Result<()> {
    if let Some(handle) = self.save_handle.take() {
      handle.save(self.to_bytes()?);
    }

    Ok(())
  }

  pub fn to_bytes(&self) -> Result<Vec<u8>> {
    let mut buffer = Vec::new();
    let data = Savedata::from(self);
    data.write(&mut buffer)?;
    Ok(buffer)
  }
}

impl From<&World> for Savedata {
  fn from(world: &World) -> Self {
    Self {
      round: world.round.clone(),
      continent: world.continent.clone(),
      player_manager: world.player_manager.clone(),
      bot_manager: world.bot_manager.clone(),
      precursor_manager: world.precursor_manager.clone(),
      military: world.military.clone(),
      ranking: world.ranking.clone(),
      report_manager: world.report_manager.clone(),
      config: Arc::unwrap_or_clone(world.config()),
      stats: world.stats.clone(),
      chat: world.chat.clone(),
    }
  }
}

impl From<Savedata> for World {
  fn from(savedata: Savedata) -> Self {
    Self {
      round: savedata.round,
      continent: savedata.continent,
      player_manager: savedata.player_manager,
      bot_manager: savedata.bot_manager,
      precursor_manager: savedata.precursor_manager,
      military: savedata.military,
      ranking: savedata.ranking,
      report_manager: savedata.report_manager,
      config: Arc::new(savedata.config),
      stats: savedata.stats,
      chat: savedata.chat,

      emitter: Emitter::default(),
      save_handle: None,
      on_next_round: None,
    }
  }
}

impl TryFrom<&World> for Vec<u8> {
  type Error = Error;

  fn try_from(world: &World) -> Result<Self> {
    world.to_bytes()
  }
}
