using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Cute;
using UnityEngine;
using Wizard.RoomMatch;
using Wizard.Scripts.Network.Data.TableData.Arena.TwoPick;

namespace Wizard.Battle.Recovery;

public class RecoveryController
{
	private NetworkBattleManagerBase _networkBattleMgr;

	private List<Coroutine> _recoveryCoroutineList = new List<Coroutine>();

	private Matching _matchingInstance;

	public RecoveryDataHandler RecoveryDataHandlerInstance { get; private set; }

	public bool IsMariganFinished => Data.BattleRecoveryInfo.IsMulliganEnd;

	public RecoveryOperationInfo AIBattleRecoveryData { get; private set; }

	public event Action OnFinishRecoveringData;

	public event Action OnFinishRecoveryLogSync;

	public RecoveryController(RecoveryOperationInfo aiBattleRecoveryData = null)
	{
		AIBattleRecoveryData = aiBattleRecoveryData;
		Format format = Data.CurrentFormat;
		if (format == Format.Max && GameMgr.GetIns().GetDataMgr().IsDipslayHighRankFormat())
		{
			format = PlayerStaticData.HighRankFormat();
		}
		PlayerStaticData.LoadUserRankTexture(format);
		switch (GameMgr.GetIns().GetDataMgr().m_BattleType)
		{
		case DataMgr.BattleType.FreeBattle:
			_matchingInstance = new Matching_Free();
			break;
		case DataMgr.BattleType.RankBattle:
			_matchingInstance = new Matching_RankMatch();
			break;
		case DataMgr.BattleType.ColosseumNormal:
		case DataMgr.BattleType.ColosseumTwoPick:
		case DataMgr.BattleType.ColosseumHof:
		case DataMgr.BattleType.ColosseumWindFall:
			_matchingInstance = new Matching_Colosseum();
			break;
		case DataMgr.BattleType.CompetitionNormal:
		case DataMgr.BattleType.CompetitionTwoPick:
			_matchingInstance = new Matching_Competition();
			break;
		case DataMgr.BattleType.RoomBattle:
			ResetRoomInfo(NetworkDefine.ServerBattleType.OpenRoom, Data.BattleRecoveryInfo, RoomConnectController.BattleRule.Bo1, Format.Max, TwoPickFormat.None, isOpenDeckRule: false);
			break;
		case DataMgr.BattleType.RoomTwoPick:
			ResetRoomInfo(NetworkDefine.ServerBattleType.RoomTwoPick, Data.BattleRecoveryInfo, Data.BattleRecoveryInfo.BattleParameterInstance.Rule, Format.Max, Data.BattleRecoveryInfo.BattleParameterInstance.TwoPickFormat, isOpenDeckRule: false);
			break;
		case DataMgr.BattleType.TwoPickBackdraft:
			ResetRoomInfo(NetworkDefine.ServerBattleType.RoomTwoPick, Data.BattleRecoveryInfo, RoomConnectController.BattleRule.Bo1, Format.Max, Data.BattleRecoveryInfo.BattleParameterInstance.TwoPickFormat, isOpenDeckRule: false);
			break;
		case DataMgr.BattleType.TwoPick:
			_matchingInstance = new Matching_TwoPick();
			break;
		case DataMgr.BattleType.Sealed:
			_matchingInstance = new Matching_Sealed();
			break;
		}
		ConnectNode();
		UIManager.GetInstance().StartCoroutine(WaitRealtimeObjectCreateToSetupRecoveryData());
	}

	private void ResetRoomInfo(NetworkDefine.ServerBattleType battleType, BattleRecoveryInfo battleRecoveryInfo, RoomConnectController.BattleRule roomRule, Format format, TwoPickFormat deckFormatType, bool isOpenDeckRule)
	{
		_matchingInstance = new Matching_Room(battleRecoveryInfo._isConventionRoom, battleRecoveryInfo.IsGatheringRoom);
		(_matchingInstance as Matching_Room).SetBattleParameter(new BattleParameter(battleType, format, deckFormatType, roomRule, isOpenDeckRule));
		RoomBase.SettingOpponentDispData(!Data.BattleRecoveryInfo.is_owner, Data.BattleRecoveryInfo.opponent_name, Data.BattleRecoveryInfo.opponent_emblem_id, Data.BattleRecoveryInfo.opponent_degree_id, Data.BattleRecoveryInfo.opponent_country_code, Data.BattleRecoveryInfo.opponent_rank, Data.BattleRecoveryInfo.IsOpponentOfficialUser, Data.BattleRecoveryInfo.OpponentHighFormatRank);
	}

	private IEnumerator WaitRealtimeObjectCreateToSetupRecoveryData()
	{
		while (ToolboxGame.RealTimeNetworkAgent == null)
		{
			_matchingInstance.UpdateOffLineMatching();
			yield return null;
		}
		ToolboxGame.RealTimeNetworkAgent.IsNotPlayReceivingData = true;
		SetupRecoveryData();
	}

	private void SetupRecoveryData()
	{
		ParseRecoveryData();
		OnRecoveryReady();
		ToolboxGame.RealTimeNetworkAgent.StartRecovery(Data.BattleRecoveryInfo.battle_id.ToString(), Data.BattleRecoveryInfo.Play_seq, Data.BattleRecoveryInfo.Pub_seq);
		if (!GameMgr.GetIns().IsAINetwork)
		{
			_recoveryCoroutineList.Add(UIManager.GetInstance().StartCoroutine(RealtimeOpenToRecoveryStart()));
		}
		_recoveryCoroutineList.Add(UIManager.GetInstance().StartCoroutine(WaitTillBattleCreate()));
	}

	private IEnumerator RealtimeOpenToRecoveryStart()
	{
		while (!ToolboxGame.RealTimeNetworkAgent.IsOpen())
		{
			yield return null;
		}
		ToolboxGame.RealTimeNetworkAgent.EmitMsgPack(NetworkBattleDefine.NetworkBattleURI.RecoveryStart);
	}

	private IEnumerator WaitTillBattleCreate()
	{
		while (BattleManagerBase.GetIns() == null || BattleManagerBase.GetIns().SBattleLoad == null || !BattleManagerBase.GetIns().SBattleLoad.isLoadEnd || !ToolboxGame.RealTimeNetworkAgent.IsOpen())
		{
			yield return null;
		}
		RecoveryEndToChangeBattleScene();
	}

	private void RecoveryEndToChangeBattleScene()
	{
		_networkBattleMgr = BattleManagerBase.GetIns() as NetworkBattleManagerBase;
		ToolboxGame.RealTimeNetworkAgent.SetNetworkBattleMgr(_networkBattleMgr);
		BattleManagerBase.GetIns().OnStartOpening += delegate
		{
			_networkBattleMgr._recoveryController = this;
			RecoveryDataHandlerInstance = new RecoveryDataHandler(_networkBattleMgr, this.OnFinishRecoveringData, this.OnFinishRecoveryLogSync, AIBattleRecoveryData);
			RecoveryDataHandlerInstance.OnBattleReceived();
		};
		_matchingInstance.GotoBattle();
		BattleManagerBase.GetIns().SBattleLoad.StartBattleScene();
	}

	private void RecoveryReturnScene()
	{
		if (!_matchingInstance.GetMatchingDataReady())
		{
			UIManager.GetInstance().OffViewAll();
		}
		ToolboxGame.DestroyNetworkAgent();
		if (_matchingInstance is Matching_Room)
		{
			RoomBase.ResetOpponentData();
		}
		if (_matchingInstance.GetMatchingDataReady() && GameMgr.GetIns().GetBattleCtrl() != null)
		{
			UIManager.GetInstance().StartCoroutine(BattleEndCoroutin(ChangeScene));
			return;
		}
		UIManager.GetInstance().CloseInSceneLoadingMatching();
		ChangeScene();
	}

	private void ChangeScene()
	{
		UIManager.ChangeViewSceneParam changeViewSceneParam = new UIManager.ChangeViewSceneParam();
		changeViewSceneParam.OnFinishChangeView = delegate
		{
			UIManager.GetInstance().CloseInSceneLoadingMatching();
			UIManager.GetInstance().CloseInSceneLoadingBattle();
		};
		UIManager.GetInstance().ChangeViewScene(UIManager.ViewScene.MyPage, changeViewSceneParam);
	}

	private IEnumerator BattleEndCoroutin(Action callback)
	{
		while (BattleManagerBase.GetIns() == null)
		{
			yield return null;
		}
		SBattleLoad battleLoad = BattleManagerBase.GetIns().SBattleLoad;
		while (!battleLoad.isLoadEnd)
		{
			yield return null;
		}
		yield return GameMgr.GetIns().GetBattleCtrl().BattleEnd();
		callback();
	}

	private void ConnectNode()
	{
		MatchingNetworkConnectChecker matchingNetworkConnectCheker = _matchingInstance._matchingNetworkConnectCheker;
		matchingNetworkConnectCheker.Start();
		matchingNetworkConnectCheker.OnConnectError = ReturnTitle;
		string battleId = Data.BattleRecoveryInfo.battle_id.ToString();
		if (GameMgr.GetIns().GetDataMgr().IsRoomBattleType())
		{
			battleId = Data.BattleRecoveryInfo.roomId.ToString();
		}
		matchingNetworkConnectCheker.SetBattleId(battleId);
		matchingNetworkConnectCheker.SetConnectOnly();
	}

	private void ReturnTitle()
	{
		for (int i = 0; i < _recoveryCoroutineList.Count; i++)
		{
			Coroutine routine = _recoveryCoroutineList[i];
			UIManager.GetInstance().StopCoroutine(routine);
			routine = null;
		}
		_recoveryCoroutineList.Clear();
		SystemText systemText = Data.SystemText;
		DialogBase dialogBase = UIManager.GetInstance().CreateDialogClose(isSystem: true);
		dialogBase.SetSize(DialogBase.Size.M);
		dialogBase.SetTitleLabel(systemText.Get("ErrorHeader_0012"));
		dialogBase.SetText(systemText.Get("Error_0012"));
		dialogBase.AddButton(DialogBase.ButtonType.BackToTitle);
		dialogBase.SetPanelDepth(6000);
		dialogBase.SetFadeButtonEnabled(flag: false);
		dialogBase.onPushButton1 = (Action)Delegate.Combine(dialogBase.onPushButton1, (Action)delegate
		{
			if (_matchingInstance.GetMatchingDataReady() && GameMgr.GetIns().GetBattleCtrl() != null)
			{
				UIManager.GetInstance().StartCoroutine(BattleEndCoroutin(SoftwareReset));
			}
			else
			{
				SoftwareReset();
			}
		});
	}

	private void SoftwareReset()
	{
		Wizard.SoftwareReset.exec();
	}

	private void OnRecoveryReady()
	{
		UIManager.GetInstance().createInSceneLoadingMatching(notBlack: true);
		UIManager.GetInstance().closeInSceneLoading();
		DataMgr dataMgr = GameMgr.GetIns().GetDataMgr();
		List<int> list = null;
		list = ((!GameMgr.GetIns().IsAINetwork) ? (from i in GameMgr.GetIns().GetNetworkUserInfoData().GetSelfDeck()
			select i.CardId).ToList() : AIBattleRecoveryData.SetupInfo.PlayerInfo.DeckCardInfos.Select((DeckCardInfo i) => i?.CardId.Value ?? 100011010).ToList());
		dataMgr.SetCurrentDeckData(list);
		dataMgr.SetPlayerCharaId(Data.BattleRecoveryInfo.chara_id);
		dataMgr.SetPlayerSubClassID(Data.BattleRecoveryInfo.SubClassId);
		dataMgr.SetPlayerMyRotationInfo(Data.BattleRecoveryInfo.MyRotationId);
		dataMgr.SetPlayerSleeveId(Data.BattleRecoveryInfo.sleeve_id);
		dataMgr.SetSelectDeckFormat(Data.BattleRecoveryInfo.deck_format);
		if (GameMgr.GetIns().IsAINetwork)
		{
			List<int> currentEnemyDeckData = AIBattleRecoveryData.SetupInfo.EnemyInfo.DeckCardInfos.Select((DeckCardInfo i) => i?.CardId.Value ?? 100011010).ToList();
			dataMgr.SetCurrentEnemyDeckData(currentEnemyDeckData);
			dataMgr.SetEnemyCharaId(AIBattleRecoveryData.SetupInfo.EnemyInfo.CharaId);
			dataMgr.SetEnemySleeveId(AIBattleRecoveryData.SetupInfo.EnemyInfo.SleeveId);
		}
		else
		{
			List<int> currentEnemyDeckData2 = (from i in GameMgr.GetIns().GetNetworkUserInfoData().GetOpponentDeck()
				select i.CardId).ToList();
			dataMgr.SetCurrentEnemyDeckData(currentEnemyDeckData2);
			dataMgr.SetEnemyCharaId(Data.BattleRecoveryInfo.chara_id);
			dataMgr.SetEnemySubClassID(Data.BattleRecoveryInfo.OpponentSubClassId);
			dataMgr.SetEnemyMyRotationInfo(Data.BattleRecoveryInfo.OpponentMyRotationId);
			dataMgr.SetEnemySleeveId(Data.BattleRecoveryInfo.sleeve_id);
		}
		int playerClassId = dataMgr.GetPlayerClassId();
		int selectDeckId = dataMgr.GetSelectDeckId();
		bool num = PlayerPrefsWrapper.GetBool(PlayerPrefsWrapper.LAST_BATTLE_IS_TRIALDECK);
		_matchingInstance.FirstSetting(playerClassId, selectDeckId, isRecovery: true);
		if (num && (Data.BattleRecoveryInfo.BattleParameterInstance.TwoPickFormat != TwoPickFormat.Chaos || Data.BattleRecoveryInfo.BattleParameterInstance.TwoPickFormat != TwoPickFormat.BackdraftChaos))
		{
			DeckData deckData = new DeckData(Format.Max, DeckAttributeType.TrialDeck);
			deckData.SetDeckID(selectDeckId);
			deckData.SetDeckClassID(playerClassId);
			deckData.SetCardIdList(list);
			deckData.SetDeckName(PlayerPrefsWrapper.GetValue(PlayerPrefsWrapper.LAST_BATTLE_NAME_TRIALDECK));
			dataMgr.SetSelectDeckId(deckData.GetDeckID());
			dataMgr.LastSelectDeckAttributeType = DeckAttributeType.TrialDeck;
			dataMgr.SetPlayerCharaIdBySkinId(deckData.GetSkinId());
		}
		else if (dataMgr.IsTwoPickBattleType())
		{
			DeckData deckData2 = new DeckData();
			deckData2.SetDeckID(0);
			deckData2.SetDeckClassID(playerClassId);
			deckData2.SetDeckSleeveID(3000011L);
			deckData2.SetDeckName(GameMgr.GetIns().GetDataMgr().GetClanNameByKey(playerClassId));
			deckData2.SetCardIdList(list);
			dataMgr.SetSelectDeckId(deckData2.GetDeckID());
			dataMgr.LastSelectDeckAttributeType = DeckAttributeType.Invalid;
			dataMgr.SetPlayerCharaIdBySkinId(Data.BattleRecoveryInfo.chara_id);
			dataMgr._roomTwoPickDeckData = deckData2;
			if (dataMgr.m_BattleType == DataMgr.BattleType.TwoPickBackdraft)
			{
				Data.RoomTwoPickInfo.deckData.classId = dataMgr.GetEnemyClassId();
				dataMgr._roomTwoPickDeckData.SetDeckClassID(dataMgr.GetEnemyClassId());
			}
			else
			{
				Data.RoomTwoPickInfo.deckData.classId = playerClassId;
			}
			Data.RoomTwoPickInfo.deckData.entryId = 0;
			Data.RoomTwoPickInfo.deckData.isSelectCompleted = true;
			Data.RoomTwoPickInfo.deckData.cardIds = deckData2.GetCardIdList().ToArray();
			Data.RoomTwoPickBeforeBattleInfo.SetSelfClassIdTwoPickDraftData(playerClassId);
			if (Data.BattleRecoveryInfo.BattleParameterInstance.TwoPickFormat == TwoPickFormat.Chaos || Data.BattleRecoveryInfo.BattleParameterInstance.TwoPickFormat == TwoPickFormat.BackdraftChaos)
			{
				CandidateChaos candidateChaos = Data.RoomTwoPickInfo.CandidateChaos;
				candidateChaos.SelectedChaosId = Data.BattleRecoveryInfo.ChaosId;
				candidateChaos.SelectedCharaId = Data.BattleRecoveryInfo.chara_id;
				candidateChaos.SelectedClassId = Data.BattleRecoveryInfo.class_id;
			}
		}
		if ((bool)ToolboxGame.RealTimeNetworkAgent)
		{
			CustomPreference.SetNodeServerURL(Data.BattleRecoveryInfo.node_server_url);
		}
	}

	private int DecideFirstUser(int id)
	{
		if (id == PlayerStaticData.UserViewerID)
		{
			return 0;
		}
		return 1;
	}

	private bool IsPlayer(int id)
	{
		if (id == PlayerStaticData.UserViewerID)
		{
			return true;
		}
		return false;
	}

	private void ParseRecoveryData()
	{
		int first_turn = Data.BattleRecoveryInfo.first_turn;
		GameMgr.GetIns().GetNetworkUserInfoData().TurnState = DecideFirstUser(first_turn);
		Dictionary<string, object> info = ParseData(isPlayer: true);
		Dictionary<string, object> info2 = ParseData(isPlayer: false);
		GameMgr.GetIns().SettingSelfInfo(info, isWatchReplayRecovery: true);
		GameMgr.GetIns().SettingOpponentInfo(info2, isWatchReplayRecovery: true);
		GameMgr.GetIns().GetNetworkUserInfoData().SetSelfDeck(Data.BattleRecoveryInfo.deck);
	}

	private Dictionary<string, object> ParseData(bool isPlayer)
	{
		Dictionary<string, object> dictionary = new Dictionary<string, object>();
		dictionary.Add("fieldId", Data.BattleRecoveryInfo.field_id);
		dictionary.Add("seed", Data.BattleRecoveryInfo.seed);
		if (isPlayer)
		{
			dictionary.Add("viewerId", Data.BattleRecoveryInfo.viewer_id);
			dictionary.Add("oppoId", Data.BattleRecoveryInfo.opponent_viewer_id);
			dictionary.Add("charaId", Data.BattleRecoveryInfo.chara_id);
			dictionary.Add("classId", Data.BattleRecoveryInfo.class_id);
			dictionary.Add("sleeveId", Data.BattleRecoveryInfo.sleeve_id);
			dictionary.Add("rank", Data.BattleRecoveryInfo.rank);
			dictionary.Add("degreeId", Data.BattleRecoveryInfo.degree_id);
			dictionary.Add("emblemId", Data.BattleRecoveryInfo.emblem_id);
			dictionary.Add("country_code", Data.BattleRecoveryInfo.country_code);
			dictionary.Add("userName", Data.BattleRecoveryInfo.name);
			dictionary.Add("isOfficial", Data.BattleRecoveryInfo.IsOfficialUser);
			dictionary.Add("chaosId", Data.BattleRecoveryInfo.ChaosId);
			dictionary.Add("subclassId", Data.BattleRecoveryInfo.SubClassId);
			dictionary.Add("rotationId", Data.BattleRecoveryInfo.MyRotationId);
		}
		else
		{
			dictionary.Add("viewerId", Data.BattleRecoveryInfo.viewer_id);
			dictionary.Add("charaId", Data.BattleRecoveryInfo.opponent_chara_id);
			dictionary.Add("classId", Data.BattleRecoveryInfo.opponent_class_id);
			dictionary.Add("sleeveId", Data.BattleRecoveryInfo.opponent_sleeve_id);
			dictionary.Add("rank", Data.BattleRecoveryInfo.opponent_rank);
			dictionary.Add("degreeId", Data.BattleRecoveryInfo.opponent_degree_id);
			dictionary.Add("emblemId", Data.BattleRecoveryInfo.opponent_emblem_id);
			dictionary.Add("country_code", Data.BattleRecoveryInfo.opponent_country_code);
			dictionary.Add("userName", Data.BattleRecoveryInfo.opponent_name);
			dictionary.Add("battlePoint", Data.BattleRecoveryInfo.opponent_battle_point);
			dictionary.Add("isMasterRank", Data.BattleRecoveryInfo.is_opponent_master_rank);
			dictionary.Add("masterPoint", Data.BattleRecoveryInfo.opponent_master_point);
			dictionary.Add("isOfficial", Data.BattleRecoveryInfo.IsOpponentOfficialUser);
			dictionary.Add("chaosId", Data.BattleRecoveryInfo.OpponentChaosId);
			dictionary.Add("subclassId", Data.BattleRecoveryInfo.OpponentSubClassId);
			dictionary.Add("rotationId", Data.BattleRecoveryInfo.OpponentMyRotationId);
		}
		dictionary.Add("isChaosSkinOverride", Data.BattleRecoveryInfo.IsChaosSkinOverride);
		return dictionary;
	}
}
