using System.Collections.Generic;
using System.Linq;

namespace Mox.Shared.Serializer
{
	public class MemoryNode
	{
		public string m_sName;
		public readonly Dictionary<string, object> m_dValues = new Dictionary<string, object>();
		public readonly List<MemoryNode> m_lChildren = new List<MemoryNode>();
		public MemoryNode m_Parent;
		public MemoryNode m_Next;
	}

	public class MemorySerializerLoad : Serializer
	{
		public MemorySerializerLoad(MemoryNode _node)
		{
			m_CurrentNode = _node;
		}

		private bool SetValue<T>(ref T _value, object _object)
		{
			if (_object.GetType() == typeof(T))
			{
				_value = (T) _object;
				return true;
			}

			return false;
		}

		public override bool Serialize(ref int _value, string _sName, int _defaultValue)
		{
			return m_CurrentNode.m_dValues.TryGetValue(_sName, out var o) && SetValue(ref _value, o);
		}

		public override bool Serialize(ref string _value, string _sName, string _defaultValue)
		{
			return m_CurrentNode.m_dValues.TryGetValue(_sName, out var o) && SetValue(ref _value, o);
		}

		public override bool Serialize(ref bool _value, string _sName, bool _defaultValue)
		{
			return m_CurrentNode.m_dValues.TryGetValue(_sName, out var o) && SetValue(ref _value, o);
		}

		public override bool StartChild(string[] _aValidTags, out string _sName)
		{
			_sName = null;
			if (m_CurrentNode.m_lChildren.Count == 0)
			{
				return false;
			}
			
			var child = m_PreviousChild == null ? m_CurrentNode.m_lChildren[0] : m_PreviousChild.m_Next;
			if (!_aValidTags.Contains(child.m_sName))
			{
				return false;
			}

			m_CurrentNode = child;
			m_PreviousChild = null;
			_sName = m_CurrentNode.m_sName;

			return true;
		}

		public override bool StartChild(string _sName)
		{
			if (m_CurrentNode.m_lChildren.Count == 0)
			{
				return false;
			}
			
			var child = m_PreviousChild == null ? m_CurrentNode.m_lChildren[0] : m_PreviousChild.m_Next;
			if (child.m_sName != _sName)
			{
				return false;
			}

			m_CurrentNode = child;
			m_PreviousChild = null;

			return true;
		}

		public override void EndChild()
		{
			m_PreviousChild = m_CurrentNode;
			m_CurrentNode = m_CurrentNode.m_Parent;
		}

		public override bool IsLoading => true;

		private MemoryNode m_PreviousChild;
		private MemoryNode m_CurrentNode;
	}
}
