using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;

namespace TeslaConsole.BattleTech;

/// <summary>
/// The recorded outcome of one BattleTech mission, saved as a gzip'd
/// BinaryFormatter blob (.btm) exactly like the RP .rpm mechanism. Mirrors
/// <c>RPMissionResults</c> minus the football branches (BT battle modes have
/// no teams, so every ranking entry is a single pilot).
/// </summary>
[Serializable]
internal class BTMissionResults
{
	private BTMission mMission;

	internal DateTime mMissionStart;

	internal TimeSpan mActuallMissionTime;

	internal readonly List<BTMissionEvent> mEvents = new List<BTMissionEvent>();

	internal readonly Dictionary<BTPlayer, int> mFinalScores = new Dictionary<BTPlayer, int>();

	public BTMission Mission => mMission;

	public DateTime MissionStart => mMissionStart;

	public TimeSpan ActuallMissionTime => mActuallMissionTime;

	public IEnumerable<BTMissionEvent> Events => mEvents;

	internal BTMissionResults(BTMission mission)
	{
		mMission = mission;
	}

	public static string GetBTMissionsDirectory()
	{
		string text = Path.Combine(Program.GetCommonAppDataDirectory(), "BT Missions");
		if (!Directory.Exists(text))
		{
			Directory.CreateDirectory(text);
		}
		return text;
	}

	public static BTMissionResults Load(string file)
	{
		using GZipStream gZipStream = new GZipStream(File.OpenRead(file), CompressionMode.Decompress);
		BinaryFormatter binaryFormatter = new BinaryFormatter();
		BTMissionResults result = (BTMissionResults)binaryFormatter.Deserialize(gZipStream);
		gZipStream.Close();
		return result;
	}

	public void Save()
	{
		string path = Path.Combine(GetBTMissionsDirectory(), mMissionStart.ToString("yyyy-MM-dd HH-mm-ss.ffff") + ".btm");
		using GZipStream gZipStream = new GZipStream(File.OpenWrite(path), CompressionMode.Compress);
		BinaryFormatter binaryFormatter = new BinaryFormatter();
		binaryFormatter.Serialize(gZipStream, this);
		gZipStream.Close();
	}

	public int GetScore(BTPlayer player)
	{
		return GetScore(player, TimeSpan.MaxValue);
	}

	public int GetScore(BTPlayer player, TimeSpan gameTime)
	{
		if (gameTime == TimeSpan.MaxValue && mFinalScores.ContainsKey(player))
		{
			return mFinalScores[player];
		}
		int result = 1000;
		TimeSpan timeSpan = TimeSpan.MinValue;
		foreach (BTMissionEvent mEvent in mEvents)
		{
			if (mEvent is BTScoreUpdateEvent && mEvent.ReportingPilot == player && mEvent.GameTime > timeSpan && mEvent.GameTime <= gameTime)
			{
				result = ((BTScoreUpdateEvent)mEvent).Score;
				timeSpan = mEvent.GameTime;
			}
		}
		return result;
	}

	public int GetFinalPlace(BTPlayer player)
	{
		int num = 1;
		int score = GetScore(player, TimeSpan.MaxValue);
		foreach (BTPlayer player2 in mMission.Players)
		{
			if (player2 != player && GetScore(player2, TimeSpan.MaxValue) > score)
			{
				num++;
			}
		}
		return num;
	}

	public BTPlayer[][] GetChartOrder()
	{
		return GetChartOrder(TimeSpan.MaxValue);
	}

	public BTPlayer[][] GetChartOrder(TimeSpan gameTime)
	{
		List<Tuple<BTPlayer[], int>> list = new List<Tuple<BTPlayer[], int>>();
		foreach (BTPlayer player in Mission.Players)
		{
			list.Add(new Tuple<BTPlayer[], int>(new BTPlayer[1] { player }, GetScore(player, gameTime)));
		}
		for (int i = 0; i < list.Count - 1; i++)
		{
			for (int j = i + 1; j < list.Count; j++)
			{
				if (list[i].B < list[j].B || (list[i].B == list[j].B && string.CompareOrdinal(list[i].A[0].Name, list[j].A[0].Name) > 0))
				{
					Tuple<BTPlayer[], int> value = list[i];
					list[i] = list[j];
					list[j] = value;
				}
			}
		}
		List<BTPlayer[]> list2 = new List<BTPlayer[]>();
		foreach (Tuple<BTPlayer[], int> item in list)
		{
			list2.Add(item.A);
		}
		return list2.ToArray();
	}

	public PrintDocument GetPrintDocument()
	{
		return new BTPrintDocument(this);
	}
}
