using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace PepperDash.Core.JsonToSimpl
{
    /// <summary>
    /// Used to interact with an array of values with the S+ modules
    /// </summary>
	public class JsonToSimplArrayLookupChild : JsonToSimplChildObjectBase
	{
        /// <summary>
        /// 
        /// </summary>
		public string SearchPropertyName { get; set; }
        /// <summary>
        /// 
        /// </summary>
		public string SearchPropertyValue { get; set; }

		int ArrayIndex;

		/// <summary>
		/// For gt2.4.1 array lookups
		/// </summary>
		/// <param name="file"></param>
		/// <param name="key"></param>
		/// <param name="pathPrefix"></param>
		/// <param name="pathSuffix"></param>
		/// <param name="searchPropertyName"></param>
		/// <param name="searchPropertyValue"></param>
		public void Initialize(string file, string key, string pathPrefix, string pathSuffix,
			string searchPropertyName, string searchPropertyValue)
		{
			base.Initialize(file, key, pathPrefix, pathSuffix);
			SearchPropertyName = searchPropertyName;
			SearchPropertyValue = searchPropertyValue;
		}


		/// <summary>
		/// For newer >=2.4.1 array lookups. 
		/// </summary>
		/// <param name="file"></param>
		/// <param name="key"></param>
		/// <param name="pathPrefix"></param>
		/// <param name="pathAppend"></param>
		/// <param name="pathSuffix"></param>
		/// <param name="searchPropertyName"></param>
		/// <param name="searchPropertyValue"></param>
		public void InitializeWithAppend(string file, string key, string pathPrefix, string pathAppend,
			string pathSuffix, string searchPropertyName, string searchPropertyValue)
		{
			string pathPrefixWithAppend = (pathPrefix != null ? pathPrefix : "") + GetPathAppend(pathAppend);
			base.Initialize(file, key, pathPrefixWithAppend, pathSuffix);

			SearchPropertyName = searchPropertyName;
			SearchPropertyValue = searchPropertyValue;
		}



		//PathPrefix+ArrayName+[x]+path+PathSuffix
		/// <summary>
		/// 
		/// </summary>
		/// <param name="path"></param>
		/// <returns></returns>
		protected override string GetFullPath(string path)
		{
			return string.Format("{0}[{1}].{2}{3}",
				PathPrefix == null ? "" : PathPrefix,
				ArrayIndex,
				path,
				PathSuffix == null ? "" : PathSuffix);
		}

        /// <summary>
        /// Process all values
        /// </summary>
		public override void ProcessAll()
		{
			if (FindInArray())
				base.ProcessAll();
		}

		/// <summary>
		/// Provides the path append for GetFullPath
		/// </summary>
		/// <returns></returns>
		string GetPathAppend(string a)
		{
			if (string.IsNullOrEmpty(a))
			{
				return "";
			}
			if (a.StartsWith("."))
			{
				return a;
			}
			else
			{
				return "." + a;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		bool FindInArray()
		{
			if (Master == null)
				throw new InvalidOperationException("Cannot do operations before master is linked");
			if (Master.JsonObject == null)
				throw new InvalidOperationException("Cannot do operations before master JSON has read");
			if (PathPrefix == null)
				throw new InvalidOperationException("Cannot do operations before PathPrefix is set");


			var token = Master.JsonObject.SelectToken(PathPrefix);
			if (token is JArray)
			{
				var array = token as JArray;
				try
				{
					var item = array.FirstOrDefault(o =>
					{
						var prop = o[SearchPropertyName];
						return prop != null && prop.Value<string>()
						.Equals(SearchPropertyValue, StringComparison.OrdinalIgnoreCase);
					});
					if (item == null)
					{
						Debug.Console(1, "JSON Child[{0}] Array '{1}' '{2}={3}' not found: ", Key,
							PathPrefix, SearchPropertyName, SearchPropertyValue);
						this.LinkedToObject = false;
						return false;
					}

					this.LinkedToObject = true;
					ArrayIndex = array.IndexOf(item);
					OnStringChange(string.Format("{0}[{1}]", PathPrefix, ArrayIndex), 0, JsonToSimplConstants.FullPathToArrayChange);
					Debug.Console(1, "JSON Child[{0}] Found array match at index {1}", Key, ArrayIndex);
					return true;
				}
				catch (Exception e)
				{
					Debug.Console(1, "JSON Child[{0}] Array '{1}' lookup error: '{2}={3}'\r{4}", Key,
						PathPrefix, SearchPropertyName, SearchPropertyValue, e);
				}
			}
			else
			{
				Debug.Console(1, "JSON Child[{0}] Path '{1}' is not an array", Key, PathPrefix);
			}

			return false;
		}
	}
}