using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using MaidStatus;
using UnityEngine;

[Serializable]
public class ScenarioData
{
	public ScenarioData(CsvParser csv, int cy)
	{
		ScenarioData $this = this;
		Action<ScenarioData.PlayableCondition, int> action = delegate(ScenarioData.PlayableCondition condition, int cx)
		{
			if (csv.IsCellToExistData(cx, cy) && !$this.m_PlayableData.ContainsKey(condition))
			{
				$this.m_PlayableData.Add(condition, new ScenarioData.PlayableData(csv.GetCellAsString(cx, cy), condition));
			}
		};
		for (int i = 0; i < csv.max_cell_x; i++)
		{
			switch (i)
			{
			case 0:
				this.ID = csv.GetCellAsInteger(i, cy);
				break;
			case 1:
				this.Title = csv.GetCellAsString(i, cy);
				break;
			case 2:
				this.EventContents = csv.GetCellAsString(i, cy);
				break;
			case 3:
				action(ScenarioData.PlayableCondition.好感度, i);
				break;
			case 4:
				action(ScenarioData.PlayableCondition.時間帯, i);
				break;
			case 5:
				action(ScenarioData.PlayableCondition.シナリオ, i);
				break;
			case 6:
				action(ScenarioData.PlayableCondition.属性, i);
				break;
			case 7:
				action(ScenarioData.PlayableCondition.パラメ\u30FCタ, i);
				break;
			case 8:
				action(ScenarioData.PlayableCondition.性癖, i);
				break;
			case 9:
				action(ScenarioData.PlayableCondition.ジョブクラス, i);
				break;
			case 10:
				action(ScenarioData.PlayableCondition.夜伽クラス, i);
				break;
			case 11:
				action(ScenarioData.PlayableCondition.関係, i);
				break;
			case 12:
				action(ScenarioData.PlayableCondition.アイテム, i);
				break;
			case 13:
				action(ScenarioData.PlayableCondition.施設, i);
				break;
			case 14:
				action(ScenarioData.PlayableCondition.NTRブロック, i);
				break;
			case 15:
				this.IconName = csv.GetCellAsString(i, cy);
				break;
			case 16:
				this.ScenarioScript = csv.GetCellAsString(i, cy);
				break;
			case 17:
			{
				string cellAsString = csv.GetCellAsString(i, cy);
				if (!string.IsNullOrEmpty(cellAsString))
				{
					this.ScriptLabel = ((cellAsString.IndexOf("*") < 0) ? ("*" + cellAsString) : cellAsString);
				}
				break;
			}
			case 18:
				this.EventMaidNum = ((!csv.IsCellToExistData(i, cy)) ? 0 : csv.GetCellAsInteger(i, cy));
				break;
			case 19:
				this.IsImportant = (csv.GetCellAsString(i, cy) == "重要");
				break;
			case 20:
				this.IsOncePlayOnly = !csv.IsCellToExistData(i, cy);
				break;
			case 21:
				this.Notification = csv.GetCellAsString(i, cy);
				break;
			case 22:
				this.ConditionText = csv.GetCellAsString(i, cy).Replace("\n", "&").Split(new char[]
				{
					'&'
				});
				break;
			}
		}
		this.CheckPlayableCondition(false);
	}

	public ScenarioData()
	{
	}

	public bool IsOncePlayed { get; private set; }

	public bool IsPlayable
	{
		get
		{
			return (!this.IsOncePlayOnly || !this.IsOncePlayed) && (this.ConditionCount == 0 || this.CheckPlayableCondition(false));
		}
	}

	public bool ImportantPlayable
	{
		get
		{
			return (!this.IsOncePlayOnly || !this.IsOncePlayed) && this.IsImportant && this.CheckPlayableCondition(true);
		}
	}

	private bool m_ContainsConditionScenario
	{
		get
		{
			return this.m_PlayableData.ContainsKey(ScenarioData.PlayableCondition.シナリオ);
		}
	}

	public int ConditionCount
	{
		get
		{
			return this.m_PlayableData.Count;
		}
	}

	public int EventMaidCount
	{
		get
		{
			return this.m_EventMaid.Count;
		}
	}

	public bool NotPlayAgain
	{
		get
		{
			return this.IsOncePlayOnly && this.IsOncePlayed;
		}
	}

	public string NotLineTitle
	{
		get
		{
			return this.Title.Replace("\n", string.Empty);
		}
	}

	public bool IsFixedMaid { get; private set; }

	public static bool operator true(ScenarioData data)
	{
		return data != null;
	}

	public static bool operator false(ScenarioData data)
	{
		return data == null;
	}

	public static bool operator !(ScenarioData data)
	{
		return data == null;
	}

	private bool CheckPlayableCondition(bool update_important = false)
	{
		bool flag = false;
		this.m_EventMaid.Clear();
		if (this.m_PlayableData == null)
		{
			return false;
		}
		this.m_ExistMaidUpdate = false;
		bool flag2 = true;
		bool flag3 = false;
		foreach (ScenarioData.PlayableCondition playableCondition in this.m_PlayableData.Keys)
		{
			if (!update_important || playableCondition != ScenarioData.PlayableCondition.時間帯)
			{
				List<Maid> before = new List<Maid>(this.m_EventMaid);
				flag = this.CheckPlayableCondition(playableCondition, true);
				if (!flag)
				{
					break;
				}
				if (!flag2 && flag3 && this.m_ExistMaidUpdate)
				{
					this.m_EventMaid = (from e in this.m_EventMaid
					where before.Contains(e)
					select e).ToList<Maid>();
					if (this.m_EventMaid.Count == 0)
					{
						flag = false;
						break;
					}
				}
				flag2 = false;
				if (!flag3)
				{
					flag3 = (this.m_EventMaid.Count > 0);
					if (this.m_ExistMaidUpdate && this.EventMaidCount == 0)
					{
						flag = false;
						break;
					}
				}
			}
		}
		flag &= this.IsEnoughEventMaid();
		return flag;
	}

	public bool CheckPlayableCondition(ScenarioData.PlayableCondition condition, bool maid_update = true)
	{
		if (!this.m_PlayableData.ContainsKey(condition))
		{
			return false;
		}
		ScenarioData.PlayableData playableData = this.m_PlayableData[condition];
		CharacterMgr characterMgr = GameMain.Instance.CharacterMgr;
		FacilityManager facilityMgr = GameMain.Instance.FacilityMgr;
		bool and_operator = playableData.StringData.IndexOf("&") >= 0;
		bool flag = playableData.StringData.IndexOf("|") >= 0;
		char c = ',';
		if (and_operator && flag)
		{
			Debug.LogError("条件演算子が混在してます");
		}
		else if (and_operator)
		{
			c = '&';
		}
		else if (flag)
		{
			c = '|';
		}
		bool isOk = and_operator;
		Action<bool> set_ok = delegate(bool set_val)
		{
			if (and_operator)
			{
				isOk = (isOk && set_val);
			}
			else
			{
				isOk = (isOk || set_val);
			}
		};
		Action<Maid> add_maid = delegate(Maid maid)
		{
			if (maid_update)
			{
				this.AddEventMaid(maid);
			}
			set_ok(true);
		};
		Action<Maid> remove_maid = delegate(Maid maid)
		{
			if (and_operator && this.m_EventMaid.Contains(maid))
			{
				set_ok(false);
			}
			if (maid_update)
			{
				this.RemoveEventMaid(maid, false);
			}
		};
		Action<Maid, bool> action = delegate(Maid maid, bool check_ok)
		{
			if (check_ok)
			{
				add_maid(maid);
			}
			else
			{
				remove_maid(maid);
			}
		};
		bool maid_check = false;
		Action action2 = delegate()
		{
			if (!maid_check && maid_update)
			{
				this.m_EventMaid.Clear();
			}
			this.m_ExistMaidUpdate = true;
			maid_check = true;
		};
		foreach (string text in playableData.StringData.Split(new char[]
		{
			c
		}))
		{
			switch (condition)
			{
			case ScenarioData.PlayableCondition.好感度:
			{
				int num = int.Parse(text);
				action2();
				for (int j = 0; j < characterMgr.GetStockMaidCount(); j++)
				{
					Maid stockMaid = characterMgr.GetStockMaid(j);
					action(stockMaid, stockMaid.status.likability >= num);
				}
				break;
			}
			case ScenarioData.PlayableCondition.時間帯:
				if (text == "昼")
				{
					set_ok(characterMgr.status.isDaytime);
				}
				else
				{
					set_ok(!characterMgr.status.isDaytime);
				}
				break;
			case ScenarioData.PlayableCondition.属性:
			{
				string[] array2 = text.Split(new char[]
				{
					'.'
				});
				action2();
				for (int k = 0; k < characterMgr.GetStockMaidCount(); k++)
				{
					Maid stockMaid2 = characterMgr.GetStockMaid(k);
					if (text.IndexOf("NPCキャラ") >= 0)
					{
						this.IsFixedMaid = true;
						if (stockMaid2.status.heroineType == HeroineType.Sub && stockMaid2.status.subCharaData.uniqueName == array2[1])
						{
							add_maid(stockMaid2);
						}
					}
					else if (text.IndexOf("NPC以外") >= 0)
					{
						action(stockMaid2, stockMaid2.status.heroineType != HeroineType.Sub);
					}
					else if (text.IndexOf("移籍") >= 0)
					{
						if (stockMaid2.status.heroineType == HeroineType.Transfer)
						{
							if (text != null)
							{
								if (text == "移籍メイド")
								{
									add_maid(stockMaid2);
									goto IL_43F;
								}
								if (text == "雇用移籍メイド")
								{
									action(stockMaid2, !stockMaid2.status.mainChara);
									goto IL_43F;
								}
							}
							string convertPersonal = GameMain.Instance.ScenarioSelectMgr.GetConvertPersonal(stockMaid2);
							if (text.IndexOf("固定") >= 0)
							{
								this.IsFixedMaid = true;
								if (text == "固定移籍メイド")
								{
									action(stockMaid2, stockMaid2.status.mainChara && ScenarioData.m_MainMaidList.Contains(convertPersonal));
								}
								else
								{
									action(stockMaid2, stockMaid2.status.mainChara && text == "固定移籍" + convertPersonal);
								}
							}
							else if (GameMain.Instance.ScenarioSelectMgr.ExistConvertData(convertPersonal))
							{
								action(stockMaid2, "移籍" + convertPersonal == text);
							}
						}
						IL_43F:;
					}
					else if (stockMaid2.status.heroineType == HeroineType.Original)
					{
						if (text != null)
						{
							if (text == "オリジナルメイド")
							{
								add_maid(stockMaid2);
								goto IL_57F;
							}
							if (text == "雇用メイド")
							{
								action(stockMaid2, !stockMaid2.status.mainChara);
								goto IL_57F;
							}
						}
						string convertPersonal2 = GameMain.Instance.ScenarioSelectMgr.GetConvertPersonal(stockMaid2);
						if (text.IndexOf("固定") >= 0)
						{
							this.IsFixedMaid = true;
							if (text == "固定メイド")
							{
								action(stockMaid2, stockMaid2.status.mainChara && ScenarioData.m_MainMaidList.Contains(convertPersonal2));
							}
							else
							{
								action(stockMaid2, stockMaid2.status.mainChara && text == "固定" + convertPersonal2);
							}
						}
						else if (GameMain.Instance.ScenarioSelectMgr.ExistConvertData(convertPersonal2))
						{
							action(stockMaid2, convertPersonal2 == text);
						}
					}
					IL_57F:;
				}
				break;
			}
			case ScenarioData.PlayableCondition.シナリオ:
			{
				int id = -1;
				ScenarioData scenarioData;
				if (int.TryParse(text, out id))
				{
					scenarioData = GameMain.Instance.ScenarioSelectMgr.GetScenarioData(id);
				}
				else
				{
					scenarioData = GameMain.Instance.ScenarioSelectMgr.GetScenarioData(text);
				}
				if (scenarioData != null)
				{
					action2();
					for (int l = 0; l < characterMgr.GetStockMaidCount(); l++)
					{
						Maid stockMaid3 = characterMgr.GetStockMaid(l);
						action(stockMaid3, scenarioData.IsOncePlayed && stockMaid3.status.GetEventEndFlag(scenarioData.ID));
					}
				}
				else if (text.IndexOf("シナリオフラグ") >= 0)
				{
					set_ok(characterMgr.status.GetFlag(text.Split(new char[]
					{
						':'
					})[1]) == 1);
				}
				else if (text.IndexOf("メイドフラグ") >= 0)
				{
					action2();
					for (int m = 0; m < characterMgr.GetStockMaidCount(); m++)
					{
						Maid stockMaid4 = characterMgr.GetStockMaid(m);
						action(stockMaid4, stockMaid4.status.GetFlag(text.Split(new char[]
						{
							':'
						})[1]) == 1);
					}
				}
				break;
			}
			case ScenarioData.PlayableCondition.パラメ\u30FCタ:
			{
				action2();
				ParametersPack parametersPack = new ParametersPack();
				for (int n = 0; n < characterMgr.GetStockMaidCount(); n++)
				{
					Maid stockMaid5 = characterMgr.GetStockMaid(n);
					parametersPack.Clear();
					parametersPack.Parse(text, ',');
					action(stockMaid5, parametersPack.GreaterThanOrEqualToStatus(stockMaid5.status));
				}
				break;
			}
			case ScenarioData.PlayableCondition.性癖:
				action2();
				for (int num2 = 0; num2 < characterMgr.GetStockMaidCount(); num2++)
				{
					Maid stockMaid6 = characterMgr.GetStockMaid(num2);
					Propensity.Data[] valueArray = stockMaid6.status.propensitys.GetValueArray();
					bool flag2 = false;
					for (int num3 = 0; num3 < valueArray.Count<Propensity.Data>(); num3++)
					{
						if (valueArray[num3].drawName == text)
						{
							flag2 = true;
							add_maid(stockMaid6);
							break;
						}
					}
					if (!flag2)
					{
						remove_maid(stockMaid6);
					}
				}
				break;
			case ScenarioData.PlayableCondition.ジョブクラス:
				action2();
				for (int num4 = 0; num4 < characterMgr.GetStockMaidCount(); num4++)
				{
					Maid stockMaid7 = characterMgr.GetStockMaid(num4);
					SortedDictionary<int, ClassData<JobClass.Data>> allDatas = stockMaid7.status.jobClass.GetAllDatas();
					bool flag3 = false;
					for (int num5 = 0; num5 < allDatas.Count<KeyValuePair<int, ClassData<JobClass.Data>>>(); num5++)
					{
						if (allDatas[num5].data.drawName == text)
						{
							flag3 = true;
							add_maid(stockMaid7);
							break;
						}
					}
					if (!flag3)
					{
						remove_maid(stockMaid7);
					}
				}
				break;
			case ScenarioData.PlayableCondition.夜伽クラス:
				action2();
				for (int num6 = 0; num6 < characterMgr.GetStockMaidCount(); num6++)
				{
					Maid stockMaid8 = characterMgr.GetStockMaid(num6);
					SortedDictionary<int, ClassData<YotogiClass.Data>> allDatas2 = stockMaid8.status.yotogiClass.GetAllDatas();
					bool flag4 = false;
					for (int num7 = 0; num7 < allDatas2.Count<KeyValuePair<int, ClassData<YotogiClass.Data>>>(); num7++)
					{
						if (allDatas2[num7].data.drawName == text)
						{
							flag4 = true;
							add_maid(stockMaid8);
							break;
						}
					}
					if (!flag4)
					{
						remove_maid(stockMaid8);
					}
				}
				break;
			case ScenarioData.PlayableCondition.関係:
				action2();
				for (int num8 = 0; num8 < characterMgr.GetStockMaidCount(); num8++)
				{
					Maid stockMaid9 = characterMgr.GetStockMaid(num8);
					action(stockMaid9, EnumConvert.GetString(stockMaid9.status.relation) == text);
				}
				break;
			case ScenarioData.PlayableCondition.アイテム:
			{
				int facilityPowerUpMaterialID = FacilityDataTable.GetFacilityPowerUpMaterialID(text);
				set_ok(facilityMgr.GetFacilityPowerUpItemEnable(facilityPowerUpMaterialID));
				break;
			}
			case ScenarioData.PlayableCondition.施設:
			{
				string[] array3 = text.Replace("Lv", " ").Split(new char[]
				{
					' '
				});
				int facilityTypeID = -1;
				if (!int.TryParse(array3[0], out facilityTypeID))
				{
					facilityTypeID = FacilityDataTable.GetFacilityTypeID(array3[0]);
				}
				if (array3.Count<string>() > 1)
				{
					set_ok(facilityMgr.IsExistTypeFacility(facilityTypeID) && facilityMgr.GetFacilityLevel(facilityTypeID) >= int.Parse(array3[1]));
				}
				else
				{
					set_ok(facilityMgr.IsExistTypeFacility(facilityTypeID));
				}
				break;
			}
			case ScenarioData.PlayableCondition.NTRブロック:
				if (text == "○")
				{
					set_ok(GameMain.Instance.CharacterMgr.status.lockNTRPlay);
				}
				else
				{
					set_ok(!GameMain.Instance.CharacterMgr.status.lockNTRPlay);
				}
				break;
			}
		}
		return isOk;
	}

	public bool IsEnoughEventMaid()
	{
		if (!this.IsFixedMaid)
		{
			return this.EventMaidNum <= this.m_EventMaid.Count;
		}
		return this.m_EventMaid.Count != 0;
	}

	public Maid GetEventMaid(int no)
	{
		return this.m_EventMaid[no];
	}

	public List<Maid> GetEventMaidList()
	{
		return this.m_EventMaid;
	}

	public bool ExistEventMaid(Maid maid)
	{
		return this.m_EventMaid.Contains(maid);
	}

	public void AddEventMaid(Maid maid)
	{
		if (!this.m_EventMaid.Contains(maid) && !maid.status.GetEventEndFlag(this.ID))
		{
			this.m_EventMaid.Add(maid);
		}
	}

	public void RemoveEventMaid(List<Maid> maid_list, bool not_again = false)
	{
		foreach (Maid maid in maid_list)
		{
			this.RemoveEventMaid(maid, not_again);
		}
	}

	public void RemoveEventMaid(Maid maid, bool not_again = false)
	{
		if (this.m_EventMaid.Contains(maid))
		{
			this.m_EventMaid.Remove(maid);
			if (not_again)
			{
				maid.status.SetEventEndFlag(this.ID, true);
			}
		}
	}

	public void ScenarioPlay(List<Maid> maid_list)
	{
		if (!this.IsFixedMaid)
		{
			for (int i = 0; i < maid_list.Count; i++)
			{
				GameMain.Instance.CharacterMgr.SetActiveMaid(maid_list[i], i);
			}
		}
		this.RemoveEventMaid(maid_list, this.m_NotMaidAgain);
		this.IsOncePlayed = true;
	}

	public ScenarioData.PlayableData[] GetPlayableDataArray()
	{
		return this.m_PlayableData.Values.ToArray<ScenarioData.PlayableData>();
	}

	public ScenarioData.PlayableData GetPlayableData(int index)
	{
		return this.m_PlayableData.Values.ElementAt(index);
	}

	public ScenarioData.PlayableData GetPlayableData(ScenarioData.PlayableCondition condition)
	{
		return (!this.m_PlayableData.ContainsKey(condition)) ? null : this.m_PlayableData[condition];
	}

	public void Serialize(BinaryWriter writer)
	{
		writer.Write(this.IsOncePlayed);
	}

	public void Deserialize(BinaryReader reader)
	{
		try
		{
			this.IsOncePlayed = reader.ReadBoolean();
			if (GameMain.Instance.ScenarioSelectMgr.nSaveVer >= 1f)
			{
				if (GameMain.Instance.ScenarioSelectMgr.nSaveVer < 1.2f)
				{
					reader.ReadInt32();
				}
			}
			else
			{
				reader.ReadBoolean();
			}
			if (GameMain.Instance.ScenarioSelectMgr.nSaveVer >= 1.1f && GameMain.Instance.ScenarioSelectMgr.nSaveVer < 1.3f)
			{
				reader.ReadBoolean();
			}
		}
		catch
		{
			if (GameMain.Instance.ScenarioSelectMgr.DeserializeFiled)
			{
				Debug.Log("ScenarioSelectMgr.cs:前のバージョンのデータです(2017/10/24より前)");
			}
			else
			{
				Debug.LogError("ScenarioSelectMgr.cs:読み込みエラー");
			}
		}
	}

	public void Recet()
	{
		this.IsOncePlayed = false;
	}

	private static string[] m_MainMaidList = new string[]
	{
		"無垢",
		"真面目",
		"凜デレ",
		"純真",
		"クーデレ",
		"ツンデレ"
	};

	public readonly int ID;

	public readonly Dictionary<ScenarioData.PlayableCondition, ScenarioData.PlayableData> m_PlayableData = new Dictionary<ScenarioData.PlayableCondition, ScenarioData.PlayableData>();

	public readonly string Title;

	public readonly string EventContents;

	public readonly string ScenarioScript;

	public readonly string ScriptLabel;

	public readonly int EventMaidNum;

	public readonly string IconName;

	public readonly bool IsImportant;

	public readonly bool IsOncePlayOnly;

	public readonly string[] ConditionText;

	public readonly string Notification;

	private List<Maid> m_EventMaid = new List<Maid>();

	private bool m_NotMaidAgain = true;

	private bool m_ExistMaidUpdate;

	public enum PlayableCondition
	{
		好感度,
		時間帯,
		属性,
		シナリオ,
		パラメ\u30FCタ,
		性癖,
		ジョブクラス,
		夜伽クラス,
		関係,
		アイテム,
		施設,
		NTRブロック,
		MAX
	}

	public class PlayableData
	{
		public PlayableData(string data, ScenarioData.PlayableCondition condition)
		{
			this.Condition = condition;
			this.StringData = data.Replace('．', '.').Replace('，', ',').Replace(',', '&');
		}

		public string[] StrdataArray
		{
			get
			{
				return this.StringData.Split(new char[]
				{
					','
				});
			}
		}

		public readonly string StringData;

		public readonly ScenarioData.PlayableCondition Condition;
	}
}
