using Sandbox.ModAPI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UIFun.Messagesv2;
using VRage.Utils;
using VRageMath;
using BlendTypeEnum = VRageRender.MyBillboard.BlendTypeEnum;



namespace UIFun.Menu.Dialog
{
	class ColorPickerDialog : DialogBox
	{

		StringBuilder EnteredRedText = new StringBuilder("255");
		StringBuilder EnteredGreenText = new StringBuilder("255");
		StringBuilder EnteredBlueText = new StringBuilder("255");
		StringBuilder EnteredAlphaText = new StringBuilder("255");
		ModHUDMessage Title = new ModHUDMessage();
		ModHUDMessage RedText= new ModHUDMessage();
		ModHUDMessage GreenText = new ModHUDMessage();
		ModHUDMessage BlueText = new ModHUDMessage();
		ModHUDMessage AlphaText = new ModHUDMessage();
		ModHUDMessage CancelButton = new ModHUDMessage();
		ModHUDMessage ConfirmButton = new ModHUDMessage();
		ModBillboardHUDMessage CancelBackground = new ModBillboardHUDMessage();
		ModBillboardHUDMessage ConfirmBackground = new ModBillboardHUDMessage();
		ModBillboardHUDMessage BoxBackground = new ModBillboardHUDMessage();
		ModBillboardHUDMessage TitleBackground = new ModBillboardHUDMessage();

		ModBillboardHUDMessage SliderRed = new ModBillboardHUDMessage();
		ModBillboardHUDMessage SliderRedBox = new ModBillboardHUDMessage();
		ModBillboardHUDMessage SliderGreen = new ModBillboardHUDMessage();
		ModBillboardHUDMessage SliderGreenBox = new ModBillboardHUDMessage();
		ModBillboardHUDMessage SliderBlue = new ModBillboardHUDMessage();
		ModBillboardHUDMessage SliderBlueBox = new ModBillboardHUDMessage();
		ModBillboardHUDMessage SliderAlpha = new ModBillboardHUDMessage();
		ModBillboardHUDMessage SliderAlphaBox = new ModBillboardHUDMessage();

		ModBillboardHUDMessage PreviewBox = new ModBillboardHUDMessage();

		float sliderposition_r = 1f, sliderposition_b = 1f, sliderposition_g = 1f, sliderposition_a = 1f;
		bool m_ShowAlpha = true;
		bool m_UseHSV = false;
		static StringBuilder CancelString = new StringBuilder("<color=red>Cancel  ");
		static StringBuilder ConfirmString = new StringBuilder("  <color=green>Confirm");
		//static StringBuilder DefaultInputColor = new StringBuilder("<color=darkgreen>");
		static MyStringId Background = MyStringId.GetOrCompute("Square");

		Action<Color> SubmitAction, UpdateAction;
		//Func<float, object> SlidertoValue;
		Action CancelAction;

		Color CurrentColor;
		SelectedColor selected = SelectedColor.none;
		enum SelectedColor
		{
			none,
			red,
			green,
			blue,
			alpha
		}

		public ColorPickerDialog()
		{
			RedText.Message = EnteredRedText;
			GreenText.Message = EnteredGreenText;
			BlueText.Message = EnteredBlueText;
			AlphaText.Message = EnteredAlphaText;
			//SlidertoValue = DefaultSliderValueConvert;

			Title.Visible = true;
			RedText.Visible = true;
			GreenText.Visible = true;
			BlueText.Visible = true;
			AlphaText.Visible = true;
			CancelButton.Visible = true;
			ConfirmButton.Visible = true;
			CancelBackground.Visible = true;
			ConfirmBackground.Visible = true;
			BoxBackground.Visible = true;
			TitleBackground.Visible = true;
			SliderRedBox.Visible = true;
			SliderRed.Visible = true;
			SliderGreenBox.Visible = true;
			SliderGreen.Visible = true;
			SliderBlueBox.Visible = true;
			SliderBlue.Visible = true;
			SliderAlphaBox.Visible = true;
			SliderAlpha.Visible = true;
			PreviewBox.Visible = true;

			Title.Origin = Vector2D.Zero;
			RedText.Origin = Vector2D.Zero;
			GreenText.Origin = Vector2D.Zero;
			BlueText.Origin = Vector2D.Zero;
			AlphaText.Origin = Vector2D.Zero;
			CancelButton.Origin = Vector2D.Zero;
			ConfirmButton.Origin = Vector2D.Zero;
			CancelBackground.Origin = Vector2D.Zero;
			ConfirmBackground.Origin = Vector2D.Zero;
			BoxBackground.Origin = Vector2D.Zero;
			TitleBackground.Origin = Vector2D.Zero;
			SliderRedBox.Origin = Vector2D.Zero;
			SliderRed.Origin = Vector2D.Zero;
			PreviewBox.Origin = Vector2D.Zero;

            Title.Scale = 1.5d;
			RedText.Scale = 1.5d;
			BlueText.Scale = 1.5d;
			GreenText.Scale = 1.5d;
			AlphaText.Scale = 1.5d;
			CancelButton.Scale = 1.5d;
			ConfirmButton.Scale = 1.5d;

			Title.Blend = BlendTypeEnum.PostPP;
			RedText.Blend = BlendTypeEnum.PostPP;
			GreenText.Blend = BlendTypeEnum.PostPP;
			BlueText.Blend = BlendTypeEnum.PostPP;
			AlphaText.Blend = BlendTypeEnum.PostPP;

			CancelButton.Message = CancelString;
			ConfirmButton.Message = ConfirmString;

			CancelBackground.BillBoardColor = Color.Black * 0.3f;
			CancelBackground.Blend = BlendTypeEnum.PostPP;
			CancelBackground.Material = Background;

			ConfirmBackground.BillBoardColor = Color.Black * 0.3f;
			ConfirmBackground.Blend = BlendTypeEnum.PostPP;
			ConfirmBackground.Material = Background;

			BoxBackground.BillBoardColor = Color.Black * 0.3f;
			BoxBackground.Blend = BlendTypeEnum.PostPP;
			BoxBackground.Material = Background;

			TitleBackground.BillBoardColor = Color.Blue * 0.3f + Color.Black * 0.5f;
			TitleBackground.Blend = BlendTypeEnum.PostPP;
			TitleBackground.Material = Background;

			SliderRedBox.Blend = BlendTypeEnum.PostPP;
			SliderRedBox.Material = Background;
			SliderRedBox.BillBoardColor = Color.Black * 0.5f;

			SliderRed.Blend = BlendTypeEnum.PostPP;
			SliderRed.Material = Background;
			SliderRed.BillBoardColor = Color.White;

			SliderGreenBox.Blend = BlendTypeEnum.PostPP;
			SliderGreenBox.Material = Background;
			SliderGreenBox.BillBoardColor = Color.Black * 0.5f;

			SliderGreen.Blend = BlendTypeEnum.PostPP;
			SliderGreen.Material = Background;
			SliderGreen.BillBoardColor = Color.White;

			SliderBlueBox.Blend = BlendTypeEnum.PostPP;
			SliderBlueBox.Material = Background;
			SliderBlueBox.BillBoardColor = Color.Black * 0.5f;

			SliderBlue.Blend = BlendTypeEnum.PostPP;
			SliderBlue.Material = Background;
			SliderBlue.BillBoardColor = Color.White;

			SliderAlphaBox.Blend = BlendTypeEnum.PostPP;
			SliderAlphaBox.Material = Background;
			SliderAlphaBox.BillBoardColor = Color.Black * 0.5f;

			SliderAlpha.Blend = BlendTypeEnum.PostPP;
			SliderAlpha.Material = Background;
			SliderAlpha.BillBoardColor = Color.White;

			PreviewBox.Blend = BlendTypeEnum.PostPP;
			PreviewBox.Material = Background;
			PreviewBox.BillBoardColor = Color.Black;


			CancelBackground.Options = Options.Shadowing;
			ConfirmBackground.Options = Options.Shadowing;
			BoxBackground.Options = Options.Shadowing;
			TitleBackground.Options = Options.Shadowing;
			SliderRedBox.Options = Options.Shadowing;
			SliderGreenBox.Options = Options.Shadowing;
			SliderBlueBox.Options = Options.Shadowing;
			SliderAlphaBox.Options = Options.Shadowing;
			PreviewBox.Options = Options.Shadowing;

			SubmitAction = null;
			
			//Refresh();
		}
		
		private void Refresh()
		{
			UpdateText();
			ConfirmButton.hasCache = false;
			CancelButton.hasCache = false;
			var ln = Title.GetLength();  //issue, if title is more than one line it screws up the math. 
			var inputln = RedText.GetLength();
			var confirmln = ConfirmButton.GetLength();
			var cancelln = CancelButton.GetLength();
			var maxX = ln.X;
			
			if (confirmln.X + cancelln.X * 2.5 > maxX)
				maxX = (confirmln.X + cancelln.X) * 2.5;
			if (inputln.X > maxX)
				maxX = inputln.X;

			Title.Offset = Vector2D.Zero;

			TitleBackground.Offset = new Vector2D(maxX / 2d, (ln.Y / 2d));
			TitleBackground.Width = (float)maxX;
			TitleBackground.Height = (float)ln.Y;

			ConfirmButton.Offset = new Vector2D(cancelln.X, ln.Y * 9d);
			CancelButton.Offset = new Vector2D(0, ln.Y * 9d);



			ConfirmBackground.Offset = (confirmln / 2) + ConfirmButton.Offset;
			ConfirmBackground.Width = (float)confirmln.X;
			ConfirmBackground.Height = (float)confirmln.Y;

			CancelBackground.Offset = (cancelln / 2) + CancelButton.Offset;
			CancelBackground.Width = (float)cancelln.X;
			CancelBackground.Height = (float)cancelln.Y;

			BoxBackground.Offset = new Vector2D(maxX / 2d, ln.Y * 5d);
			BoxBackground.Width = (float)maxX;
			BoxBackground.Height = (float)inputln.Y * 10f;

			PreviewBox.Offset = new Vector2D(-maxX / 2.5d, ln.Y * 5d);
			PreviewBox.Width = (float)maxX / 2.5f;
			PreviewBox.Height = (float)inputln.Y * 10f;


			SetOffsets(RedText, SliderRedBox, SliderRed, maxX, 2, ln.Y, sliderposition_r);
			SetOffsets(GreenText, SliderGreenBox, SliderGreen, maxX, 4, ln.Y, sliderposition_g);
			SetOffsets(BlueText, SliderBlueBox, SliderBlue, maxX, 6, ln.Y, sliderposition_b);
			SetOffsets(AlphaText, SliderAlphaBox, SliderAlpha, maxX, 8, ln.Y, sliderposition_a);

		}

		private void SetOffsets(ModHUDMessage alphaText, ModBillboardHUDMessage sliderBox, ModBillboardHUDMessage slider, double maxX, double offsety, double yheight, float sliderposition)
		{
			double bg_offset = offsety + 0.5d;
            alphaText.Offset = new Vector2D(0, yheight * (offsety - 1d));

            sliderBox.Height = (float)yheight / 2f;
			sliderBox.Width = (float)(maxX);
			sliderBox.Offset = new Vector2D(maxX / 2f, yheight * bg_offset);

			slider.Height = (float)yheight / 1.9f;
			slider.Width = (float)(maxX) / 10f;
			slider.Offset = new Vector2D(MathHelper.Lerp(0 + maxX / 20d, (float)(maxX) - maxX / 20d, sliderposition), yheight * bg_offset);
		}

		public void Request(StringBuilder title, Color initialColor, Action<Color> callback, Action<Color> updateCallback, Action OnCancel, bool ShowAlpha, bool useHSV = false)
		{
			//MyAPIGateway.Utilities.ShowMessage("Request", initialColor.ToString());
			Reset();

			//sliderposition = MathHelper.Clamp(initialvalue, 0f, 1f);//cant assume a max value of 1. 
			Active = true;
			Title.Message = title;
			SubmitAction = callback;
			UpdateAction = updateCallback;
			CancelAction = OnCancel;
			CurrentColor = initialColor;
			m_ShowAlpha = ShowAlpha;
			m_UseHSV = useHSV;
			//UpdateText();
			UpdateShowAlpha();
			SetSliders();
			///EnteredText.Clear();
			Refresh();
		}
		private void UpdateShowAlpha()
		{
			AlphaText.Visible = m_ShowAlpha;
			SliderAlphaBox.Visible = m_ShowAlpha;
			SliderAlpha.Visible = m_ShowAlpha;
		}
		private void SetSliders()
		{
			//MyAPIGateway.Utilities.ShowMessage("SetSliders", CurrentColor.ToString());
			if(m_UseHSV)
			{
				var hsv = CurrentColor.ColorToHSV();
				sliderposition_r = hsv.X;
				sliderposition_g = hsv.Y;
				sliderposition_b = hsv.Z;
				sliderposition_a = CurrentColor.A / 255f;
				UpdateText();
				return;
				
			}
			sliderposition_r = CurrentColor.R / 255f;
			sliderposition_g = CurrentColor.G / 255f;
			sliderposition_b = CurrentColor.B / 255f;
			sliderposition_a = CurrentColor.A / 255f;
			UpdateText();
		}

		public override void onClick(Vector2D MousePosition, bool left, bool right)
		{
			base.onClick(MousePosition, left, right);
			if (!left)
				return;
			var ln = CancelButton.GetLength();
			var xstart = SliderRedBox.Origin.X;
			var totalx = SliderRedBox.Width + SliderRedBox.Origin.X;
			var pos = CancelButton.Origin + CancelButton.Offset;
			var pos2 = pos + ln;
			BoundingBox2D Area = new BoundingBox2D(new Vector2D(pos.X, pos2.Y), new Vector2D(pos2.X, pos.Y));
			if (Area.Contains(MousePosition) == ContainmentType.Contains)
			{
				Cancel();
			}
			ln = ConfirmButton.GetLength();

			pos = ConfirmButton.Origin + ConfirmButton.Offset;
			pos2 = pos + ln;
			Area = new BoundingBox2D(new Vector2D(pos.X, pos2.Y), new Vector2D(pos2.X, pos.Y));
			if (Area.Contains(MousePosition) == ContainmentType.Contains)
			{
				Submit();
			}
			if(MousePosition.X > xstart && MousePosition.X < totalx)
			{
				if (MousePosition.Y < SliderRedBox.Origin.Y + SliderRedBox.Offset.Y - SliderRedBox.Height
					&& MousePosition.Y > SliderRedBox.Origin.Y + SliderRedBox.Offset.Y + SliderRedBox.Height)
				{
					selected = SelectedColor.red;
				}
				if (MousePosition.Y < SliderGreenBox.Origin.Y + SliderGreenBox.Offset.Y - SliderGreenBox.Height
					&& MousePosition.Y > SliderGreenBox.Origin.Y + SliderGreenBox.Offset.Y + SliderGreenBox.Height)
				{
					selected = SelectedColor.green;
				}
				if (MousePosition.Y < SliderBlueBox.Origin.Y + SliderBlueBox.Offset.Y - SliderBlueBox.Height
					&& MousePosition.Y > SliderBlueBox.Origin.Y + SliderBlueBox.Offset.Y + SliderBlueBox.Height)
				{
					selected = SelectedColor.blue;
				}
				if (MousePosition.Y < SliderAlphaBox.Origin.Y + SliderAlphaBox.Offset.Y - SliderAlphaBox.Height
					&& MousePosition.Y > SliderAlphaBox.Origin.Y + SliderAlphaBox.Offset.Y + SliderAlphaBox.Height)
				{
					selected = SelectedColor.alpha;
				}
			}


		}

		public override void onMouseRelease(Vector2D MousePosition, bool left, bool right)
		{
			if (!left)
				return;
			selected = SelectedColor.none;
			base.onMouseRelease(MousePosition, left, right);
		}

		public override void onMouseOver(Vector2D MousePosition)
		{
			switch(selected)
			{

				case SelectedColor.red:
					ManipluateSlider(ref sliderposition_r, MousePosition, SliderRedBox, SliderRed);
					break;
				case SelectedColor.blue:
					ManipluateSlider(ref sliderposition_b, MousePosition, SliderBlueBox, SliderBlue);
					break;
				case SelectedColor.green:
					ManipluateSlider(ref sliderposition_g, MousePosition, SliderGreenBox, SliderGreen);
					break;
				case SelectedColor.alpha:
					if(m_ShowAlpha)
					{
						ManipluateSlider(ref sliderposition_a, MousePosition, SliderAlphaBox, SliderAlpha);
					}
					break;
				default:
					break;
			}
			base.onMouseOver(MousePosition);
		}
		public void ManipluateSlider(ref float sliderposition, Vector2D MousePosition, ModBillboardHUDMessage sliderBox, ModBillboardHUDMessage slider)
		{
			var xstart = sliderBox.Origin.X + (sliderBox.Width / 20f);
			var totalx = xstart + sliderBox.Width - (sliderBox.Width / 10f);
			var perc = MousePosition.X - xstart;
			sliderposition = MathHelper.Lerp(0f, 1f, (float)(perc / totalx));
			sliderposition = MathHelper.Clamp(sliderposition, 0f, 1f);
			slider.Offset.X = MathHelper.Lerp(xstart, totalx, sliderposition);
			UpdateText();
		}

		private void UpdateText()
		{
			if (!m_UseHSV)
				CurrentColor = new Color(sliderposition_r, sliderposition_g, sliderposition_b, sliderposition_a);
			else
			{
				CurrentColor = new Vector3(sliderposition_r, sliderposition_g, sliderposition_b).HSVtoColor();
				CurrentColor.A = (byte)(sliderposition_a * 255f);
			}
				
		
			PreviewBox.BillBoardColor = CurrentColor;
            EnteredRedText.Clear();
			if(m_UseHSV)
				EnteredRedText.AppendFormat($"Hue    {(sliderposition_r * 360f):N1}°");
			else
				EnteredRedText.AppendFormat($"Red    {(sliderposition_r * 255f):N0}");
			EnteredGreenText.Clear();
			if (m_UseHSV)
				EnteredGreenText.AppendFormat($"Saturation    {(sliderposition_g * 100f):N1}%");
			else
				EnteredGreenText.AppendFormat($"Green    {(sliderposition_g * 255f):N0}");

			EnteredBlueText.Clear();
			if (m_UseHSV)
				EnteredBlueText.AppendFormat($"Value    {(sliderposition_b * 100f):N1}%");
			else
				EnteredBlueText.AppendFormat($"Blue    {(sliderposition_b * 255f):N0}");


			EnteredAlphaText.Clear();
			EnteredAlphaText.Append($"Alpha {(sliderposition_a * 255f):N0}");
		}

		public override void Cancel()
		{
			if (CancelAction != null)
				CancelAction();
			Reset();
			base.Cancel();
		}

		public override void Reset()
		{
			CancelAction = null;
			SubmitAction = null;
			//EnteredText.Clear();
			//SlidertoValue = DefaultSliderValueConvert;
		}

		public void Submit()
		{
			if (SubmitAction != null)
				SubmitAction(CurrentColor);
			Reset();
			Active = false;
		}

		public override void Draw()
		{
			
			base.Draw();

			Title.Draw();
			RedText.Draw();
			GreenText.Draw();
			BlueText.Draw();
			if(m_ShowAlpha)
			{
				AlphaText.Draw();
			}
	
			CancelButton.Draw();
			ConfirmButton.Draw();
			CancelBackground.Draw();
			ConfirmBackground.Draw();
			BoxBackground.Draw();
			TitleBackground.Draw(); 

			SliderRed.Draw();
			SliderRedBox.Draw();
			SliderGreen.Draw();
			SliderGreenBox.Draw();
			SliderBlue.Draw();
			SliderBlueBox.Draw();
			if(m_ShowAlpha)
			{
				SliderAlpha.Draw();
				SliderAlphaBox.Draw();
			}


			PreviewBox.Draw();
			
		}
	}
}

