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

namespace Mox.Shared.Serializer
{
	public class XmlSerializerLoad : Serializer
	{
		public XmlSerializerLoad(string _sXml)
		{
			m_sXml = _sXml;
			m_iCursor = 0;
		}

		public override bool Serialize(ref int _value, string _sName, int _defaultValue)
		{
			if (SerializeValue(_sName, out var sValue))
			{
				_value = Convert.ToInt32(sValue);

				return true;
			}

			return false;
		}

		public override bool Serialize(ref string _value, string _sName, string _defaultValue)
		{
			if (SerializeValue(_sName, out var sValue))
			{
				_value = sValue;

				return true;
			}

			return false;
		}

		public override bool Serialize(ref bool _value, string _sName, bool _defaultValue)
		{
			if (SerializeValue(_sName, out var sValue))
			{
				_value = Convert.ToBoolean(sValue);

				return true;
			}

			return false;
		}

		private bool SerializeValue(string _sName, out string _sValue)
		{
			var iStartIndex = m_sXml.IndexOf(" " + _sName + "=\"", m_iCursor, StringComparison.InvariantCulture);
			var iEndIndex = m_sXml.IndexOf(">", m_iCursor, StringComparison.InvariantCulture);

			if (iStartIndex == -1 || iStartIndex > iEndIndex)
			{
				_sValue = null;
				return false;
			}

			iEndIndex = iStartIndex + 3 + _sName.Length;
			var iValStart = iEndIndex;
			iEndIndex = m_sXml.IndexOf("\"", iEndIndex, StringComparison.InvariantCulture);
			_sValue = m_sXml.Substring(iValStart, iEndIndex - iValStart);

			return true;
		}

		public override bool StartChild(string[] _aValidTags, out string _sName)
		{
			var iStartIndex = m_sXml.IndexOf("<", m_iCursor, StringComparison.InvariantCulture);
			var iEndIndex = m_sXml.IndexOf(">", m_iCursor, StringComparison.InvariantCulture);

			if (m_sXml[iEndIndex - 1] != '/')
			{
				iEndIndex = m_Children.Count == 0 ? m_sXml.Length : m_sXml.IndexOf("</" + m_Children.Peek() + ">", m_iCursor, StringComparison.InvariantCulture);
			}

			if (iStartIndex == -1 || iStartIndex > iEndIndex)
			{
				_sName = null;
				return false;
			}

			iEndIndex = -1;
			for (int i = iStartIndex; i < m_sXml.Length; ++i)
			{
				if (m_sXml[i] == ' ' || m_sXml[i] == '/' || m_sXml[i] == '>')
				{
					iEndIndex = i;
					break;
				}
			}

			if (iEndIndex == -1)
			{
				_sName = null;
				return false;
			}

			_sName = m_sXml.Substring(iStartIndex + 1, iEndIndex - iStartIndex - 1);

			if (_aValidTags.Contains(_sName))
			{
				m_Children.Push(_sName);
				m_iCursor = iStartIndex + _sName.Length + 1;
				return true;
			}
			else
			{
				return false;
			}
		}

		public override bool StartChild(string _sName)
		{
			var iStartIndex = m_sXml.IndexOf("<" + _sName, m_iCursor, StringComparison.InvariantCulture);
			var iEndIndex = m_Children.Count == 0 ? m_sXml.Length : m_sXml.IndexOf("</" + m_Children.Peek() + ">", m_iCursor, StringComparison.InvariantCulture);

			if (iStartIndex == -1 || iStartIndex > iEndIndex)
			{
				return false;
			}

			m_Children.Push(_sName);
			m_iCursor = iStartIndex + _sName.Length + 1;

			return true;
		}

		public override void EndChild()
		{
			m_Children.Pop();
			var iEndIndex = m_sXml.IndexOf("/", m_iCursor, StringComparison.InvariantCulture);
			iEndIndex = m_sXml.IndexOf(">", iEndIndex, StringComparison.InvariantCulture);
			m_iCursor = iEndIndex + 1;
		}

		public override bool IsLoading { get { return true; } }

		private readonly string m_sXml;
		private readonly Stack<string> m_Children = new Stack<string>();
		private int m_iCursor;
	}
}
