using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Telerik.WinControls.UI;

namespace TelerikTestReal
{
	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();
		}

		private TestParEditorCollection items = new TestParEditorCollection();

		private void MainForm_Load(object sender, EventArgs e)
		{
			var gridBehavior = radGridView1.GridBehavior as BaseGridBehavior;
			gridBehavior.UnregisterBehavior(typeof(GridViewDataRowInfo));
			gridBehavior.RegisterBehavior(typeof(GridViewDataRowInfo), new CustomGridRowBehavior());

			var col = radGridView1.Columns["colTestType"] as GridViewComboBoxColumn;
			col.ValueMember = "Value";
			col.DisplayMember = "Display";
			col.DataSource = ((TestType[])Enum.GetValues(typeof(TestType))).Select(v => new { Value = v, Display = v.ToString() }).ToList();
			radGridView1.Relations.AddSelfReference(radGridView1.MasterTemplate, "colGridID", "colGridParentID");
			//radGridView1.TableElement.ShowSelfReferenceLines = true;

			int nr = 1;
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.RefRovina, R = 10, Fi = 100, Min = 10.1f, Max = 11.1f });
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.FiOffset, R = 11, Fi = 101, Min = 10.2f, Max = 11.2f });
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.AbsVyska, R = 12, Fi = 102, Min = 10.3f, Max = 11.3f });
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.RelVyska, R = 13, Fi = 103, Min = 10.4f, Max = 11.4f });
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.RozdielVysky, R = 14, Fi = 104, Min = 10.5f, Max = 11.5f });
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.RozdielVyskyOblast, R = 15, Fi = 105, Min = 10.6f, Max = 11.6f });
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.TestNitu, R = 16, Fi = 106, Min = 10.7f, Max = 11.7f });
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.TestZatky, R = 17, Fi = 107, Min = 10.8f, Max = 11.8f });
			items.Add(new TestParItem() { Code = $"P{nr++}", TestType = TestType.TestKolika, R = 18, Fi = 108, Min = 10.9f, Max = 11.9f });

			radGridView1.DataSource = items.EditorItems;

			foreach (var row in radGridView1.Rows)
				row.IsExpanded = true;
		}

		private void radGridView1_DataError(object sender, GridViewDataErrorEventArgs e)
		{
			radGridView1.CancelEdit();
			MessageBox.Show("Invalid data format.", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
		}

		private void radGridView1_CellClick(object sender, GridViewCellEventArgs e)
		{
			// automatic combo expanding
			if (radGridView1.IsInEditMode)
				return;

			if ((e.ColumnIndex < 0) || (e.RowIndex < 0))
				return;

			var cell = sender as GridComboBoxCellElement;
			if (cell == null)
				return;

			radGridView1.BeginEdit();
			var editor = cell.Editor as RadDropDownListEditor;
			if (editor == null)
				return;

			var el = editor.EditorElement as RadDropDownListEditorElement;
			if (el == null)
				return;

			el.ShowPopup();
		}

		private void radGridView1_CellFormatting(object sender, CellFormattingEventArgs e)
		{
			if ((e.ColumnIndex < 0) || (e.RowIndex < 0))
				return;

			var ed = e.Row.DataBoundItem as TestParEditorItem;
			if (ed == null)
				return;

			bool isSub = ed.IsSubItem;
			bool hasSub = !isSub && ed.SubItems.Count > 0;

			switch (e.Column.Name)
			{
				case "colR":
				case "colFi":
				case "colComment":
					if (isSub)
						e.CellElement.Text = "";
					break;

				case "colMin":
				case "colMax":
					if (hasSub)
					{
						e.CellElement.Text = "";
						//e.CellElement.DrawFill = true;
						//e.CellElement.BackColor = Color.Yellow;
					}
					break;

				case "colTestType":
					if (isSub)
					{
						e.CellElement.Text = ed.SubItemName;
						e.CellElement.Padding = new Padding(30, 0, 0, 0);
					}
					break;
			}
		}

		private void radGridView1_CellBeginEdit(object sender, GridViewCellCancelEventArgs e)
		{
			if ((e.ColumnIndex < 0) || (e.RowIndex < 0))
				return;

			var ed = e.Row.DataBoundItem as TestParEditorItem;
			if (ed == null)
				return;

			bool isSub = ed.IsSubItem;
			bool hasSub = !isSub && ed.SubItems.Count > 0;

			switch (e.Column.Name)
			{
				case "colR":
				case "colFi":
				case "colComment":
					if (isSub)
						e.Cancel = true;
					break;

				case "colMin":
				case "colMax":
					if (hasSub)
						e.Cancel = true;
					break;

				case "colTestType":
					if (isSub)
						e.Cancel = true;
					break;
			}
		}

		private void tsBtnRefresh_Click(object sender, EventArgs e)
		{
			items.EditorItems.ResetBindings();
			foreach (var row in radGridView1.Rows)
				row.IsExpanded = true;
		}

		private void tsEditNew_Click(object sender, EventArgs e)
		{
			//items.Add();
			items.Add(TestType.TestZatky);

			var row = GetLastGridViewItemRow();
			if (row != null)
			{
				row.IsExpanded = true;

				radGridView1.ClearSelection();
				radGridView1.CurrentRow = row;
				radGridView1.CurrentColumn = radGridView1.Columns[0];
			}
		}

		private void tsEditDelete_Click(object sender, EventArgs e)
		{
			if (radGridView1.SelectedRows.Count == 0)
			{
				MessageBox.Show("No selected rows");
				return;
			}

			var rows = GetSelectedRows().Where(r => r.IsItem).ToList();
			if (rows.Count == 0)
			{
				MessageBox.Show("No selected items");
				return;
			}

			if (MessageBox.Show($"Do you really want to delete {rows.Count} items?", "", MessageBoxButtons.OKCancel) != DialogResult.OK)
				return;

			items.Remove(rows);
		}

		private void tsEditUp_Click(object sender, EventArgs e)
		{
			if (radGridView1.SelectedRows.Count == 0)
				return;
			if (radGridView1.Rows[0].IsSelected)
				return;

			var allRows = GetSelectedRows();
			var rows = allRows.Where(o => o.IsItem).ToList();
			if (rows.Count == 0)
				return;

			var currRow = (radGridView1.CurrentRow.DataBoundItem as TestParEditorItem).DataObject;

			items.MoveUp(rows);

			foreach (var row in radGridView1.Rows)
				row.IsExpanded = true;

			Select(allRows.Select(r => r.DataObject).AsQueryable(), currRow);
		}

		private void tsEditDown_Click(object sender, EventArgs e)
		{
			if (radGridView1.SelectedRows.Count == 0)
				return;
			if (GetLastGridViewItemRow().IsSelected)
				return;

			var allRows = GetSelectedRowsDesc();
			var rows = allRows.Where(o => o.IsItem).ToList();
			if (rows.Count == 0)
				return;

			var currRow = (radGridView1.CurrentRow.DataBoundItem as TestParEditorItem).DataObject;

			items.MoveDown(rows);

			foreach (var row in radGridView1.Rows)
				row.IsExpanded = true;

			Select(allRows.Select(r => r.DataObject).AsQueryable(), currRow);
		}

		private List<TestParEditorItem> GetSelectedRows()
		{
			return radGridView1.SelectedRows.Where(r => r.DataBoundItem is TestParEditorItem).OrderBy(r => r.Index).Select(r => r.DataBoundItem as TestParEditorItem).ToList();
		}

		private List<TestParEditorItem> GetSelectedRowsDesc()
		{
			return radGridView1.SelectedRows.Where(r => r.DataBoundItem is TestParEditorItem).OrderByDescending(r => r.Index).Select(r => r.DataBoundItem as TestParEditorItem).ToList();
		}

		private GridViewRowInfo GetLastGridViewItemRow()
		{
			if (radGridView1.RowCount == 0)
				return null;

			for (int i = radGridView1.RowCount - 1; i >= 0; i--)
			{
				var row = radGridView1.Rows[i];
				var ed = row.DataBoundItem as TestParEditorItem;
				if (ed == null)
					continue;

				if (ed.IsItem)
					return row;
			}

			return null;
		}

		private void Select(IQueryable<object> rows, object currentRow)
		{
			if (rows.Count() == 0)
				return;

			if (currentRow == null)
				currentRow = rows.Last();

			foreach (var row in radGridView1.Rows)
			{
				var obj = row.DataBoundItem as TestParEditorItem;
				if (obj == null)
					continue;

				if (obj.DataObject == currentRow)
				{
					radGridView1.CurrentRow = row;
					radGridView1.CurrentColumn = radGridView1.Columns[0];
				}
			}

			foreach (var row in radGridView1.Rows)
			{
				var obj = row.DataBoundItem as TestParEditorItem;
				if (obj == null)
					continue;

				row.IsSelected = rows.Contains(obj.DataObject);
			}
		}

		private void timerUpdate_Tick(object sender, EventArgs e)
		{
			sslStatus.Text = $"SelectedRows: {radGridView1.SelectedRows.Count}, SelectedCells: {radGridView1.SelectedCells.Count}";
		}

		private void tsBtnTest_Click(object sender, EventArgs e)
		{
		}
	}

	public class CustomGridRowBehavior : GridRowBehavior
	{
		protected override bool OnMouseDownLeft(MouseEventArgs e)
		{
			var cell = GetCellAtPoint(e.Location);

			if (cell is GridRowHeaderCellElement)
				SwitchSelectionMode(GridViewSelectionMode.FullRowSelect);

			if (cell is GridDataCellElement)
				SwitchSelectionMode(GridViewSelectionMode.CellSelect);

			return base.OnMouseDownLeft(e);
		}

		protected override bool ProcessLeftKey(KeyEventArgs keys)
		{
			SwitchSelectionMode(GridViewSelectionMode.CellSelect);

			return base.ProcessLeftKey(keys);
		}

		protected override bool ProcessRightKey(KeyEventArgs keys)
		{
			SwitchSelectionMode(GridViewSelectionMode.CellSelect);

			return base.ProcessRightKey(keys);
		}

		private void SwitchSelectionMode(GridViewSelectionMode selectionMode)
		{
			if (GridViewElement.GridControl.SelectionMode != selectionMode)
				GridViewElement.GridControl.SelectionMode = selectionMode;
		}
	}
}
