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
{
	public class HudMenuScrollBox : MenuObject
	{
		private string BoxHeaderText;
		ModHUDMessage HeaderText = new ModHUDMessage();
		ModHUDMessage ListText = new ModHUDMessage();

		float y_height = 0f;
		float x_width = 0f;
		int selectedline = 0;
		int hoverline = 0;
		ModBillboardHUDMessage HeaderBackground = new ModBillboardHUDMessage();
		ModBillboardHUDMessage ScrollBackground = new ModBillboardHUDMessage();
		ModBillboardHUDMessage HighlightBarBackground = new ModBillboardHUDMessage();
		ModBillboardHUDMessage HighlightSelectBackground = new ModBillboardHUDMessage();
		ModBillboardHUDMessage ScrollSlider = new ModBillboardHUDMessage();
		ModBillboardHUDMessage ScrollSliderBackground = new ModBillboardHUDMessage();

		int m_RightSpacing = 0;
		float m_Sliderposition = 0f;

		bool m_SliderActive = false;

		int MAXLISTSIZE = 15;
		int m_listoffset = 0;

		double SCALE = 1.25f;

		public HudMenuScrollBox(Vector2D position, bool visible = true, MenuObject parent = null, Action mouseOver = null, Action onClick = null, string headerText = "", int rightpadding = 0) : base(position, visible, parent, mouseOver, onClick)
		{
			BoxHeaderText = headerText;
			HeaderText.Message.Append("<color=255,255,255,255>" + BoxHeaderText);
			HeaderText.Origin = ScreenPosition();
			HeaderText.Visible = true;
			HeaderText.Scale = SCALE;
			HeaderText.Blend = BlendTypeEnum.PostPP;
			HeaderText.Options = Options.None;

			ListText.Origin = ScreenPosition();
			ListText.Visible = true;
			ListText.Scale = SCALE;
			ListText.Blend = BlendTypeEnum.PostPP;
			ListText.Options = Options.None;
			

			HeaderBackground.Origin = ScreenPosition();
			HeaderBackground.Visible = true;
			HeaderBackground.Options = Options.Shadowing;
			HeaderBackground.BillBoardColor = Color.Black * 0.8f;
			HeaderBackground.Material = MyStringId.GetOrCompute("Square");
			HeaderBackground.Blend = BlendTypeEnum.PostPP;

			Vector2D ln = HeaderText.GetLength();
			Size = ln;
			y_height = (float)ln.Y;
			x_width = (float)ln.X;
			ListText.Offset.Y = y_height;
            HeaderBackground.Offset = ln / 2;
			HeaderBackground.Width = x_width;
			HeaderBackground.Height = y_height;

			ScrollBackground.Origin = ScreenPosition();
			ScrollBackground.Visible = true;
			ScrollBackground.Options = Options.Shadowing;
			ScrollBackground.BillBoardColor = Color.Black * 0.2f;
			ScrollBackground.Material = MyStringId.GetOrCompute("Square");
			ScrollBackground.Blend = BlendTypeEnum.PostPP;
			ScrollBackground.Offset = ln / 2;
			ScrollBackground.Offset.Y += y_height;
			ScrollBackground.Width = x_width;
			ScrollBackground.Height = y_height;

			HighlightBarBackground.Origin = ScreenPosition();
			HighlightBarBackground.Visible = true;
			HighlightBarBackground.Options = Options.Shadowing;
			HighlightBarBackground.BillBoardColor = Color.Blue * 0.3f;
			HighlightBarBackground.Material = MyStringId.GetOrCompute("Square");
			HighlightBarBackground.Blend = BlendTypeEnum.PostPP;

			HighlightSelectBackground.Origin = ScreenPosition();
			HighlightSelectBackground.Visible = true;
			HighlightSelectBackground.Options = Options.Shadowing;
			HighlightSelectBackground.BillBoardColor = Color.Blue * 0.8f;
			HighlightSelectBackground.Material = MyStringId.GetOrCompute("Square");
			HighlightSelectBackground.Blend = BlendTypeEnum.Standard;

			ScrollSliderBackground.Origin = ScreenPosition();
			ScrollSliderBackground.Blend = BlendTypeEnum.PostPP;
			ScrollSliderBackground.Visible = true;
			ScrollSliderBackground.Material = MyStringId.GetOrCompute("Square");
			ScrollSliderBackground.BillBoardColor = Color.Black * 0.5f;
			ScrollSliderBackground.Options = Options.Shadowing;

			ScrollSlider.Origin = ScreenPosition();
			ScrollSlider.Blend = BlendTypeEnum.PostPP;
			ScrollSlider.Material = MyStringId.GetOrCompute("Square");
			ScrollSlider.BillBoardColor = Color.White;
			ScrollSlider.Visible = false;
			


			m_RightSpacing = rightpadding;
		}
		public override void AddSubObject(MenuObject obj)
		{
			//only accept scrollitems as subobjects. 
			if(obj is ScrollItem)
			{
				base.AddSubObject(obj);
				UpdateList();
            }
		}
		public void SetHeaderText(string newText)
		{
			if(newText != BoxHeaderText)
			{
				BoxHeaderText = newText;
                HeaderText.Message.Clear();
				HeaderText.Message.Append("<color=255,255,255,255>" + BoxHeaderText);
				UpdateBounds();
			}
		}
		public override void UpdateBounds()
		{
			//if(Parent != null)
			//{
			//	this.Offset.Y = 0d;
			//	this.Offset.X = Parent.Size.X;
			//}
			base.UpdateBounds();
			//update position of elements. 
			Vector2D ln = HeaderText.GetLength();
			Vector2D ln2 = ListText.GetLength();
			y_height = (float)ln.Y;

			var ScreenPos = ScreenPosition();
            HeaderText.Origin = ScreenPos;
			HeaderText.hasCache = false;
			HeaderBackground.Origin = ScreenPos;
			ListText.Origin = ScreenPos;
			ListText.hasCache = false;
			ScrollBackground.Origin = ScreenPos;
			HighlightBarBackground.Origin = ScreenPos;
			HighlightSelectBackground.Origin = ScreenPos;
			ScrollSlider.Origin = ScreenPos;
			ScrollSliderBackground.Origin = ScreenPos;

			ListText.Offset.Y = y_height;

			if(ln.X < ln2.X)
			{
				ln.X = ln2.X;
			}
			else
			{
				ln2.X = ln.X;
			}
			var offset = ln / 2d;
            HeaderBackground.Offset = offset;
			HeaderBackground.Width = (float)ln.X;
			HeaderBackground.Height = y_height;
			HighlightBarBackground.Width = (float)ln.X;
			HighlightBarBackground.Height =  y_height;

			HighlightBarBackground.Offset.X = offset.X;

            HighlightSelectBackground.Width = (float)ln.X;
			HighlightSelectBackground.Height = y_height;
			HighlightSelectBackground.Offset.X = offset.X;

			ScrollBackground.Offset = ln2 / 2d;
			ScrollBackground.Offset.Y += y_height;
			ScrollBackground.Height = (float)ln2.Y;
			ScrollBackground.Width = (float)ln2.X;

			ScrollSliderBackground.Offset = ln2;
			ScrollSliderBackground.Offset.Y /= 2;
			ScrollSliderBackground.Offset.Y += y_height;
			ScrollSliderBackground.Offset.X += (float)FontTexture.xSPPix * 5f;
			ScrollSliderBackground.Height = (float)ln2.Y;
			ScrollSliderBackground.Width = (float)FontTexture.xSPPix * 10f;
			

			//sliderOriginOffset = y_height;

			ScrollSlider.Offset = ln2;
			ScrollSlider.Offset.Y /= 2;
			ScrollSlider.Offset.X += (float)FontTexture.xSPPix * 5f;
			ScrollSlider.Offset.Y += y_height;
			
			ScrollSlider.Height = (float)ln2.Y / 10f;
			ScrollSlider.Width = (float)FontTexture.xSPPix * 10f;

			UpdateSliderPosition();

			ln.Y += ln2.Y;
			ln.X += (float)FontTexture.xSPPix * 10f;
            ln.X += FontTexture.xSPPix * m_RightSpacing;
			Size = ln;
		}

		private void UpdateSliderPosition()
		{
			var ystart = (ScrollSliderBackground.Height / 20f) - (y_height);
			var totaly = ystart + (ScrollSliderBackground.Height - (ScrollSliderBackground.Height / 10f));
			ScrollSlider.Offset.Y = ScrollSliderBackground.Height - MathHelper.Lerp(totaly, ystart, m_Sliderposition);
			UpdateList(false);
		}

		public override void OnClick(Vector2D MousePosition)
		{
			if (!Visible)
				return;
			if ((MousePosition.X <= m_Max.X) && (MousePosition.X >= m_Min.X) && (MousePosition.Y <= m_Max.Y) && (MousePosition.Y >= m_Min.Y))
			{
				if (MousePosition.X >= m_Max.X - (ScrollSliderBackground.Width + m_RightSpacing * FontTexture.xSPPix) )
				{
					if(MousePosition.X <= m_Max.X - (m_RightSpacing * FontTexture.xSPPix))
					{
						if (!m_SliderActive)
						{
							if (m_SubItems.Count > MAXLISTSIZE)
								m_SliderActive = true;
						}
						else
						{
							m_SliderActive = false;
						}

					}
					onClickCallbackCall();
					foreach (var item in m_SubItems)
					{
						if (item.Visible)
							item.OnClick(MousePosition);
					}
					return;
				}
				
				
				int newselctedline = MouseToLine(MousePosition.Y);

				if(newselctedline == selectedline || newselctedline == 0 || newselctedline - m_listoffset <= 0)
				{
					if(Selected != null)
					{
						Selected.Visible = false;
						Selected.UnSelect();
						selectedline = 0;
						Selected = null;
					}
				}
				else
				{
					if (Selected != null)
					{

						Selected.Visible = false;
						Selected.UnSelect();
						Selected = null;
						selectedline = newselctedline;
						Selected = m_SubItems[selectedline  - 1];
						if (((ScrollItem)Selected).Selectable)
						{
							Selected.Visible = true;
							Selected.Select();
						}
						else
						{
							selectedline = 0;
                        }

						Selected.onClickCallbackCall();
					}
					else
					{
						selectedline = newselctedline;
						Selected = m_SubItems[selectedline  - 1];

						if(((ScrollItem)Selected).Selectable)
						{
							Selected.Visible = true;
							Selected.Select();
						}
						else
						{
							selectedline = 0;
                        }
						Selected.onClickCallbackCall();
					}
				}
				onClickCallbackCall();
			}
			foreach (var item in m_SubItems)
			{
				if (item.Visible)
					item.OnClick(MousePosition);
			}
			//base.OnClick(Position);


		}
		public override void OnMouseOver(Vector2D MousePosition)
		{
			if(m_SliderActive && ScrollSlider.Visible)
			{
				//var ystart = ScrollSliderBackground.Origin.Y + (ScrollSliderBackground.Height / 20f) - (y_height / 2) + 1;
				var ystart = (ScrollSliderBackground.Height / 20f) - (y_height);
				var totaly = ystart + (ScrollSliderBackground.Height - (ScrollSliderBackground.Height / 10f));
				var perc =  (MousePosition.Y - (ScrollSliderBackground.Origin.Y + ScrollSliderBackground.Offset.Y + (-ScrollSliderBackground.Height / 20f) + ScrollSliderBackground.Height / 2 )) / (ystart - totaly);
				m_Sliderposition = MathHelper.Lerp(1f, 0f, (float)(perc));
				m_Sliderposition = MathHelper.Clamp(m_Sliderposition, 0f, 1f);
				ScrollSlider.Offset.Y = ScrollSliderBackground.Height - MathHelper.Lerp(totaly, ystart, m_Sliderposition);
				UpdateList(false);
			}
			if ((MousePosition.X <= m_Max.X) && (MousePosition.X >= m_Min.X) && (MousePosition.Y <= m_Max.Y) && (MousePosition.Y >= m_Min.Y))
			{
				hoverline = MouseToLine(MousePosition.Y);
				if (MousePosition.X >= m_Max.X - (ScrollSliderBackground.Width + m_RightSpacing * FontTexture.xSPPix))
				{
					hoverline = 0;
				}
				else
				{
					if(!m_SliderActive)
					{
						var change = -MyAPIGateway.Input.DeltaMouseScrollWheelValue();
						change = MathHelper.Clamp(change, -1, 1);
						var cnt = m_SubItems.Count;
						var remainder = (cnt - MAXLISTSIZE);
						m_Sliderposition = MathHelper.Clamp( (float)(m_listoffset + change) / (float)remainder, 0f, 1f);
						UpdateList();
					}
				}
            }
			else
			{
				hoverline = 0;
			}
			base.OnMouseOver(MousePosition);
		}
		public override void OnMouseRelease(Vector2D Position)
		{
			m_SliderActive = false;
			base.OnMouseRelease(Position);
		}
		internal int MouseToLine(double mouseY)
		{
			var line = (int)Math.Floor((mouseY - m_Max.Y) / y_height) + m_listoffset;
			if (line > 0 && line <= m_SubItems.Count)
				return line;
			return 0;
		}
		internal void UpdateList(bool updatebounds = true)
		{
			ListText.Message.Clear();
			var cnt = m_SubItems.Count;
			if (cnt > MAXLISTSIZE)
			{
				ScrollSlider.Visible = true;
				var remainder = (cnt - MAXLISTSIZE);
				m_listoffset = (int)Math.Round(m_Sliderposition * remainder, 0);
				ScrollSlider.BillBoardColor = Color.White;

			}
			else
			{
				ScrollSlider.Visible = false;
				m_listoffset = 0;
				ScrollSlider.BillBoardColor = Color.Gray;
			}
			for (int i = m_listoffset; i < m_SubItems.Count && i < m_listoffset + MAXLISTSIZE; i++)
			{
				var item = m_SubItems[i];
				ListText.Message.Append(item.ToString());
			}
			if(updatebounds)
				UpdateBounds();
		}
		public override void Draw()
		{
			if (!Visible)
				return;
			HeaderBackground.Draw();
			HeaderText.Draw();
			ScrollBackground.Draw();
			ListText.Draw();
			if (m_MouseHover && hoverline != 0 && hoverline - m_listoffset > 0)
			{
				HighlightBarBackground.Offset.Y = HeaderBackground.Offset.Y + (double)((hoverline - m_listoffset) * y_height);
				HighlightBarBackground.Draw();
            }
			if(Selected != null && selectedline != 0 && selectedline - m_listoffset > 0)
			{
				HighlightSelectBackground.Offset.Y = HeaderBackground.Offset.Y + (double)((selectedline - m_listoffset) * y_height);
				HighlightSelectBackground.Draw();
            }
			//if we have more than 15 items.
			ScrollSliderBackground.Draw();
			if (ScrollSlider.Visible)
				ScrollSlider.Draw();


			base.Draw();
		}
		public override void Refresh()
		{
			HeaderText.hasCache = false;
			ListText.hasCache = false;
			UpdateBounds();
            base.Refresh();
		}
	}
}
