using System;
using System.Windows.Media;
using Aitex.Core.RT.Event;

namespace Aitex.Core.RT.SCCore
{
	public class SCConfigItem
	{
		public event EventHandler<object> OnValueChanged;

		public string Name { get; set; }

		public string Path { get; set; }

		public string Default { get; set; }

		public string Min { get; set; }

		public string Max { get; set; }

		public string Unit { get; set; }

		public string Type { get; set; }

		public string Tag { get; set; }

		public string Parameter { get; set; }

		public string Description { get; set; }

        public bool Visible { get; set; } = true;

        public object Value => Type switch
		{
			"Bool" => BoolValue, 
			"Double" => DoubleValue, 
			"String" => StringValue, 
			"Integer" => IntValue, 
			"Color" => ColorValue,
			_ => null, 
		};

		public Type Typeof => Type switch
		{
			"Bool" => typeof(bool), 
			"Double" => typeof(double), 
			"String" => typeof(string), 
			"Integer" => typeof(int), 
			"Color" => typeof(Color),
			_ => null, 
		};

		public string PathName => string.IsNullOrEmpty(Path) ? Name : (Path + "." + Name);

		public int IntValue { get; set; }

		public double DoubleValue { get; set; }

		public bool BoolValue { get; set; }

		public string StringValue { get; set; }
		
		public string ColorValue { get; set; }

		#region Methods

		public bool SafeSetValue(object value)
		{
			var result = false;
			switch (Type)
			{
				case "Bool":
				{
					if (bool.TryParse(value.ToString(), out var result2) && result2 != BoolValue)
					{
						BoolValue = result2;
						result = true;
					}
					break;
				}
				case "Integer":
				{
					if (int.TryParse(value.ToString(), out var result6) && result6 != IntValue)
					{
						int.TryParse(Min, out var result7);
						int.TryParse(Max, out var result8);
						if (result6 < result7 || result6 > result8)
						{
							EV.PostWarningLog("System", $"SC {PathName} value  {result6} out of setting range ({Min}, {Max})");
						}
						else
						{
							IntValue = result6;
							result = true;
						}
					}
					break;
				}
				case "Double":
				{
					if (double.TryParse(value.ToString(), out var result3) && Math.Abs(result3 - DoubleValue) > 0.0001)
					{
						double.TryParse(Min, out var result4);
						double.TryParse(Max, out var result5);
						if (result3 < result4 || result3 > result5)
						{
							EV.PostWarningLog("System", $"SC {PathName}  value  {result3} out of setting range ({Min}, {Max})");
						}
						else
						{
							DoubleValue = result3;
							result = true;
						}
					}
					break;
				}
				case "String":
					if (value.ToString() != StringValue)
					{
						StringValue = value.ToString();
						result = true;
					}
					break;
				
				case "Color":
					if (value.ToString() != ColorValue)
					{
						ColorValue = value.ToString();
						result = true;
					}
					break;
			}
			
			HandleOnValueChangedEvent(Value);
			
			return result;
		}

		public bool SetValue(object value)
		{
			var isValueChanged = false;
			switch (Type)
			{
				case "Bool":

					if (bool.TryParse(value.ToString(), out var bValue))
					{
						if (bValue != BoolValue)
						{
							BoolValue = bValue;
							isValueChanged = true;
						}
					}

					break;

				case "Integer":
				{
					if (int.TryParse(value.ToString(), out var iValue))
					{
						if (iValue != IntValue)
						{
							IntValue = iValue;
							isValueChanged = true;
						}
					}

					break;
				}
				case "Double":
				{
					if (double.TryParse(value.ToString(), out var dbValue))
					{
						if (Math.Abs(dbValue - DoubleValue) > 0.0001)
						{
							DoubleValue = dbValue;
							isValueChanged = true;
						}
					}

					break;
				}
				case "String":
				{
					var strValue = (string)value;
					if (strValue != StringValue)
					{
						StringValue = strValue;
						isValueChanged = true;
					}

					break;
				}

				case "Color":
					if (value.ToString() != ColorValue)
					{
						ColorValue = value.ToString();
						isValueChanged = true;
					}

					break;
			}

			if (isValueChanged)
			{
				HandleOnValueChangedEvent(Value);
			}

			return isValueChanged;
		}

        public bool ValueEquals(object value)
        {
            switch (Type)
            {
                case "Bool":
                    {
                        if (bool.TryParse(value.ToString(), out var result2) && result2 == BoolValue)
                        {
                            return true;
                        }
                        break;
                    }
                case "Integer":
                    {
                        if (int.TryParse(value.ToString(), out var result6) && result6 == IntValue)
                        {
                            return true;
                        }
                        break;
                    }
                case "Double":
                    {
                        if (double.TryParse(value.ToString(), out var result3) && Math.Abs(result3 - DoubleValue) <= 0.0001)
                        {
                            return true;
                        }
                        break;
                    }
                case "String":
                    if (value.ToString() == StringValue)
                    {
                        return true;
                    }
                    break;
                
                case "Color":
	                if (value.ToString() == ColorValue)
		                return true;
	                break;
            }
            return false;
        }

        public SCConfigItem Clone()
		{
			return new SCConfigItem
			{
				Name = Name,
				Path = Path,
				Default = Default,
				Min = Min,
				Max = Max,
				Unit = Unit,
				Type = Type,
				Tag = Tag,
				Parameter = Parameter,
				Description = Description,
				StringValue = StringValue,
				IntValue = IntValue,
				DoubleValue = DoubleValue,
				BoolValue = BoolValue,
				ColorValue = ColorValue
			};
		}

		private void HandleOnValueChangedEvent(object newValue)
		{
			OnValueChanged?.Invoke(this, newValue);
		}
		
		#endregion
	}
}
