using System;
using System.Collections.Generic;
using System.IO;
using MaidStatus.CsvData;
using UnityEngine;
using wf;

namespace MaidStatus
{
	public class JobClassSystem : IClassSystem<JobClass.Data>
	{
		public JobClassSystem(Status status)
		{
			this.status = status;
			this.classDatas_ = new SortedDictionary<int, ClassData<JobClass.Data>>();
			this.datas = new ReadOnlySortedDictionary<int, ClassData<JobClass.Data>>(this.classDatas_);
			this.oldClassDatas_ = new SortedDictionary<int, ClassData<JobClass.Data>>();
			this.oldDatas = new ReadOnlySortedDictionary<int, ClassData<JobClass.Data>>(this.oldClassDatas_);
		}

		public override ReadOnlySortedDictionary<int, ClassData<JobClass.Data>> datas { get; protected set; }

		public override ReadOnlySortedDictionary<int, ClassData<JobClass.Data>> oldDatas { get; protected set; }

		public override Status status { get; protected set; }

		public override ClassData<JobClass.Data> Add(JobClass.Data data, bool setOpenFlag, bool updateBonusStatus = true)
		{
			if (data != null)
			{
				if (!JobClass.IsEnabled(data.id))
				{
					Debug.LogError(string.Concat(new string[]
					{
						"メイド[",
						this.status.fullNameJpStyle,
						"]はジョブクラス[",
						data.drawName,
						"]を覚えようとしましたが,有効ではないので覚えられません"
					}));
					return null;
				}
				if (!data.learnConditions.isLearnPossiblePersonal(this.status.personal))
				{
					Debug.LogError(string.Concat(new string[]
					{
						"メイド[",
						this.status.fullNameJpStyle,
						"]はジョブクラス[",
						data.drawName,
						"]を覚えようとしましたが,現在の性格[",
						this.status.personal.drawName,
						"]では覚えられません"
					}));
					return null;
				}
			}
			ClassData<JobClass.Data> classData = null;
			if (data != null)
			{
				if (data.classType != AbstractClassData.ClassType.Old)
				{
					if (!this.classDatas_.ContainsKey(data.id))
					{
						classData = new ClassData<JobClass.Data>(new Action(this.status.UpdateClassBonusStatus));
						classData.data = data;
						classData.expSystem.SetExreienceList(new List<int>(data.experiences));
						this.classDatas_.Add(data.id, classData);
					}
					classData = this.classDatas_[data.id];
					if (data.classType == AbstractClassData.ClassType.Share && !this.oldClassDatas_.ContainsKey(classData.data.id))
					{
						this.oldClassDatas_.Add(classData.data.id, classData);
					}
					if (this.classDatas_.Count == 1)
					{
						this.status.ChangeJobClass(classData.data);
					}
					if (setOpenFlag)
					{
						GameMain.Instance.CharacterMgr.status.AddJobClassOpenFlag(data.id);
					}
				}
				else if (data.classType == AbstractClassData.ClassType.Old && !this.oldClassDatas_.ContainsKey(data.id))
				{
					classData = new ClassData<JobClass.Data>(new Action(this.status.UpdateClassBonusStatus));
					classData.data = data;
					classData.expSystem.SetExreienceList(new List<int>(data.experiences));
					this.oldClassDatas_.Add(data.id, classData);
				}
				if (updateBonusStatus)
				{
					this.status.UpdateClassBonusStatus();
				}
			}
			return classData;
		}

		public override void Remove(JobClass.Data data, bool updateBonusStatus = true)
		{
			if (data != null)
			{
				if (this.classDatas_.ContainsKey(data.id))
				{
					this.classDatas_.Remove(data.id);
				}
				if (this.oldClassDatas_.ContainsKey(data.id))
				{
					this.oldClassDatas_.Remove(data.id);
				}
				if (updateBonusStatus)
				{
					this.status.UpdateClassBonusStatus();
				}
			}
			if (this.status.selectedJobClass == null)
			{
				using (SortedDictionary<int, ClassData<JobClass.Data>>.Enumerator enumerator = this.classDatas_.GetEnumerator())
				{
					if (enumerator.MoveNext())
					{
						KeyValuePair<int, ClassData<JobClass.Data>> keyValuePair = enumerator.Current;
						this.status.ChangeJobClass(keyValuePair.Value.data);
					}
				}
			}
		}

		public void Clear()
		{
			this.classDatas_.Clear();
			this.oldClassDatas_.Clear();
		}

		public override JobClass.Data IdToClass(int id)
		{
			return (!JobClass.Contains(id)) ? null : JobClass.GetData(id);
		}

		public override void Serialize(BinaryWriter binary)
		{
			binary.Write((short)this.classDatas_.Count);
			foreach (KeyValuePair<int, ClassData<JobClass.Data>> keyValuePair in this.classDatas_)
			{
				binary.Write(keyValuePair.Key);
				keyValuePair.Value.Serialize(binary);
			}
			binary.Write((short)this.oldClassDatas_.Count);
			foreach (KeyValuePair<int, ClassData<JobClass.Data>> keyValuePair2 in this.oldClassDatas_)
			{
				binary.Write(keyValuePair2.Key);
				bool flag = !this.classDatas_.ContainsKey(keyValuePair2.Key);
				binary.Write(flag);
				if (flag)
				{
					keyValuePair2.Value.Serialize(binary);
				}
			}
		}

		public override void Deserialize(BinaryReader binary, int version)
		{
			Func<int, ClassData<JobClass.Data>> func = delegate(int classId)
			{
				JobClass.Data data2 = (!JobClass.Contains(classId)) ? null : JobClass.GetData(classId);
				ClassData<JobClass.Data> classData3 = new ClassData<JobClass.Data>(new Action(this.status.UpdateClassBonusStatus));
				classData3.data = data2;
				if (data2 != null)
				{
					classData3.expSystem.SetExreienceList(new List<int>(data2.experiences));
				}
				classData3.Deserialize(binary, version);
				Action<SimpleExperienceSystem> onChangeLevelEvent = classData3.expSystem.onChangeLevelEvent;
				classData3.expSystem.onChangeLevelEvent = null;
				classData3.expSystem.Update();
				classData3.expSystem.onChangeLevelEvent = onChangeLevelEvent;
				return classData3;
			};
			this.classDatas_.Clear();
			int num = (int)binary.ReadInt16();
			for (int i = 0; i < num; i++)
			{
				int num2 = binary.ReadInt32();
				ClassData<JobClass.Data> classData = func(num2);
				if (JobClass.IsEnabled(num2) && classData.data.learnConditions.isLearnPossiblePersonal(this.status.personal))
				{
					this.classDatas_.Add(num2, classData);
				}
			}
			if (211 >= version)
			{
				return;
			}
			this.oldClassDatas_.Clear();
			num = (int)binary.ReadInt16();
			for (int j = 0; j < num; j++)
			{
				int num3 = binary.ReadInt32();
				bool flag = binary.ReadBoolean();
				if (flag)
				{
					ClassData<JobClass.Data> classData2 = func(num3);
					if (JobClass.IsEnabled(num3) && classData2.data.learnConditions.isLearnPossiblePersonal(this.status.personal))
					{
						this.oldClassDatas_.Add(num3, classData2);
					}
				}
				else if (JobClass.IsEnabled(num3) && this.classDatas_.ContainsKey(num3))
				{
					this.oldClassDatas_.Add(this.classDatas_[num3].data.id, this.classDatas_[num3]);
				}
			}
			Dictionary<int, ClassData<JobClass.Data>> dictionary = new Dictionary<int, ClassData<JobClass.Data>>();
			Dictionary<int, ClassData<JobClass.Data>> dictionary2 = new Dictionary<int, ClassData<JobClass.Data>>();
			Dictionary<int, ClassData<JobClass.Data>> dictionary3 = new Dictionary<int, ClassData<JobClass.Data>>();
			for (int k = 0; k < 2; k++)
			{
				SortedDictionary<int, ClassData<JobClass.Data>> sortedDictionary = (k != 0) ? this.oldClassDatas_ : this.classDatas_;
				foreach (KeyValuePair<int, ClassData<JobClass.Data>> keyValuePair in sortedDictionary)
				{
					JobClass.Data data = keyValuePair.Value.data;
					AbstractClassData.ClassType classType = data.classType;
					if (classType == AbstractClassData.ClassType.New && !dictionary2.ContainsKey(data.id))
					{
						dictionary2.Add(data.id, keyValuePair.Value);
					}
					else if (classType == AbstractClassData.ClassType.Old && !dictionary3.ContainsKey(data.id))
					{
						dictionary3.Add(data.id, keyValuePair.Value);
					}
					else if (classType == AbstractClassData.ClassType.Share && !dictionary.ContainsKey(data.id))
					{
						dictionary.Add(data.id, keyValuePair.Value);
					}
				}
			}
			this.classDatas_.Clear();
			this.oldClassDatas_.Clear();
			foreach (KeyValuePair<int, ClassData<JobClass.Data>> keyValuePair2 in dictionary)
			{
				this.classDatas_.Add(keyValuePair2.Key, keyValuePair2.Value);
				this.oldClassDatas_.Add(keyValuePair2.Key, keyValuePair2.Value);
			}
			foreach (KeyValuePair<int, ClassData<JobClass.Data>> keyValuePair3 in dictionary2)
			{
				this.classDatas_.Add(keyValuePair3.Key, keyValuePair3.Value);
			}
			foreach (KeyValuePair<int, ClassData<JobClass.Data>> keyValuePair4 in dictionary3)
			{
				this.oldClassDatas_.Add(keyValuePair4.Key, keyValuePair4.Value);
			}
		}

		protected override List<JobClass.Data> GetAllBaseClassData()
		{
			return JobClass.GetAllDatas(true);
		}
	}
}
