using System;

namespace TeslaConsole.BattleTech;

/// <summary>
/// Records the in-match Munga event messages of one BattleTech mission into a
/// <see cref="BTMissionResults" />. Mirrors <c>RPMissionRecorder</c>; the event
/// set follows the BT messages in Munga Net.dll (Mech* / EndMission).
/// </summary>
internal class BTMissionRecorder
{
	private BTMissionResults mMissionResults;

	private bool mStartSet;

	public BTMissionRecorder(BTMission mission)
	{
		mMissionResults = new BTMissionResults(mission);
	}

	public void SetMissionStart()
	{
		if (mStartSet)
		{
			throw new InvalidOperationException();
		}
		mMissionResults.mMissionStart = DateTime.Now;
		mStartSet = true;
	}

	private void ValidatePlayer(BTPlayer player, string param)
	{
		if (player == null)
		{
			throw new ArgumentNullException(param);
		}
		foreach (BTPlayer player2 in mMissionResults.Mission.Players)
		{
			if (player2 == player)
			{
				return;
			}
		}
		throw new ArgumentException(param);
	}

	private TimeSpan GetMissionTime()
	{
		if (!mStartSet)
		{
			return TimeSpan.Zero;
		}
		return DateTime.Now - mMissionResults.mMissionStart;
	}

	public void PlayerKilled(BTPlayer reportingPlayer, BTPlayer killer)
	{
		ValidatePlayer(reportingPlayer, "reportingPlayer");
		ValidatePlayer(killer, "killer");
		TimeSpan missionTime = GetMissionTime();
		mMissionResults.mEvents.Add(new BTKilledEvent(reportingPlayer, missionTime, killer));
	}

	public void PlayerDeathWithoutHonor(BTPlayer reportingPlayer)
	{
		ValidatePlayer(reportingPlayer, "reportingPlayer");
		TimeSpan missionTime = GetMissionTime();
		mMissionResults.mEvents.Add(new BTDeathWithoutHonorEvent(reportingPlayer, missionTime));
	}

	public void PlayerScoreUpdate(BTPlayer reportingPlayer, int score)
	{
		ValidatePlayer(reportingPlayer, "reportingPlayer");
		TimeSpan missionTime = GetMissionTime();
		mMissionResults.mEvents.Add(new BTScoreUpdateEvent(reportingPlayer, missionTime, score));
	}

	public void PlayerDamaged(BTPlayer reportingPlayer, BTPlayer damager, int damageLoss, int pointsTransfered, int damageZoneIndex, bool damageZoneDestroyed, int weaponIndex)
	{
		ValidatePlayer(reportingPlayer, "reportingPlayer");
		ValidatePlayer(damager, "damager");
		TimeSpan missionTime = GetMissionTime();
		mMissionResults.mEvents.Add(new BTDamagedEvent(reportingPlayer, missionTime, damager, damageLoss, pointsTransfered, damageZoneIndex, damageZoneDestroyed, weaponIndex));
	}

	public void PlayerFinalScore(BTPlayer reportingPlayer, int finalScore)
	{
		ValidatePlayer(reportingPlayer, "reportingPlayer");
		mMissionResults.mFinalScores.Add(reportingPlayer, finalScore);
	}

	public BTMissionResults EndMission(TimeSpan missionLength)
	{
		mMissionResults.mActuallMissionTime = missionLength;
		BTMissionResults result = mMissionResults;
		mMissionResults = null;
		return result;
	}
}
