//
// Copyright (c) 2021, MindFusion LLC - Bulgaria.
//

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

using MindFusion.Diagramming;
using MindFusion.Diagramming.WinForms;


namespace MindFusion.Tools.ShapeDesigner
{
	/// <summary>
	/// Summary description for MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();

			settings = new Settings(shapeDesigner1);
			settings.Load();
		}

		protected override void OnClosing(CancelEventArgs e)
		{
			base.OnClosing(e);
			// ShowGrid may be changed by context menu, so synchronize before save
			settings.LoadFromDesigner();
			try
			{
				settings.Save();
			}
			catch
			{
				// installation dir may be readonly
			}
		}

		private void shapeDesigner1_ShapeChanged(object sender, EventArgs e)
		{
			// update source
			textBox1.Lines = shapeDesigner1.ExportTemplateCode(ShapeDesignerCtrl.SourceCodeLanguage.CSharp);
			textBox2.Lines = shapeDesigner1.ExportTemplateCode(ShapeDesignerCtrl.SourceCodeLanguage.VB);

			textBox1.Text = "// C# ShapeTemplate definition\r\n" + textBox1.Text;
			textBox2.Text = "' VB.NET ShapeTemplate definition\r\n" + textBox2.Text;

			// update flowchart
			flowChart1.Diagram.ClearAll();

			flowChart1.Diagram.DefaultShape = shapeDesigner1.Shape;

			//Box b = flowChart1.CreateBox(0, 0, 70, 70);
			ShapeNode b = new ShapeNode(flowChart1.Diagram);
			b.Bounds = new RectangleF(0, 0, 70, 70);
			flowChart1.Diagram.Nodes.Add(b);
			// Do not change default ImageAlign, because it can't be restored on load
			// TODO: add persistent property ImageAlign to ShapeTemplate and use it as
			// default for Boxes
			//b.ImageAlign = ImageAlign.Stretch;
			b.PolygonalTextLayout = true;
			b.Text = "Some text to test the shape text area... " +
				"The formatting algorithm is designed to layout " +
				"text inside polygonal outlines ... The formatting algorithm is ";
            b.Brush = new MindFusion.Drawing.SolidBrush(Color.FromArgb(102, 154, 204));

			// update listbox

			//shapeListBox1.Invalidate();
			if (shapeListBox1.SelectedIndex != -1)
			{
				shapeListBox1.InvalidateShapeAt(shapeListBox1.SelectedIndex);
				//				shapeListBox1.SetShapeAt(shapeListBox1.SelectedIndex, shapeDesigner1.createShapeTemplate());
			}
		}

		private void menuItem7_Click(object sender, EventArgs e)
		{
			Close();
		}

		private void menuItem2_Click(object sender, EventArgs e)
		{
			HelpForm fh = new HelpForm();
			fh.ShowDialog(this);
		}

		private Color SelectColor(Color oldColor)
		{
			using (ColorDialog colorDialog = new ColorDialog())
			{
				colorDialog.Color = oldColor;
				return colorDialog.ShowDialog() == DialogResult.OK ? colorDialog.Color : oldColor;
			}
		}

		private void menuItemBackgroundColor_Click(object sender, EventArgs e)
		{
			settings.BackgroundColor = SelectColor(shapeDesigner1.BackColor);
		}

		private void menuItemGridColor_Click(object sender, EventArgs e)
		{
			settings.GridColor = SelectColor(shapeDesigner1.GridColor);
		}

		private void menuItemOutlineColor_Click(object sender, EventArgs e)
		{
			settings.OutlineColor = SelectColor(shapeDesigner1.OutlineColor);
		}

		private void menuItemDecorationColor_Click(object sender, System.EventArgs e)
		{
			settings.DecorationColor = SelectColor(shapeDesigner1.DecorationColor);
		}

		private void menuItemTextAreaColor_Click(object sender, System.EventArgs e)
		{
			settings.TextAreaContourColor = SelectColor(shapeDesigner1.TextAreaContourColor);
		}

		private void menuItemMainContourColor_Click(object sender, System.EventArgs e)
		{
			settings.MainContourColor = SelectColor(shapeDesigner1.MainContourColor);
		}

		private void menuItemSelectionColor_Click(object sender, System.EventArgs e)
		{
			settings.SelectionColor = SelectColor(shapeDesigner1.SelectionColor);
		}

		private void menuItemGridSpacing_Click(object sender, EventArgs e)
		{
			using (GridSizeForm frmGridSize = new GridSizeForm("Set Grid Spacing", "Grid Spacing:"))
			{
				frmGridSize.Value = shapeDesigner1.GridSpacing;
				if (frmGridSize.ShowDialog() == DialogResult.OK)
					settings.GridSpacing = (int)frmGridSize.Value;
			}
		}

		private void menuItemShapeSize_Click(object sender, System.EventArgs e)
		{
			using (GridSizeForm frmGridSize = new GridSizeForm("Set Shape Size", "Shape Size:"))
			{
				frmGridSize.Maximum = SystemInformation.PrimaryMonitorSize.Width;
				frmGridSize.Value = shapeDesigner1.ShapeSize;
				if (frmGridSize.ShowDialog() == DialogResult.OK)
					shapeDesigner1.ShapeSize = (int)frmGridSize.Value;
			}
		}

		private void menuItemRoundRectRadius_Click(object sender, System.EventArgs e)
		{
			using (GridSizeForm frmGridSize = new GridSizeForm("Set Round Rectangle Radius", "Radius:"))
			{
				frmGridSize.Maximum = 100;
				frmGridSize.Value = shapeDesigner1.RoundRectRadius;
				if (frmGridSize.ShowDialog() == DialogResult.OK)
					shapeDesigner1.RoundRectRadius = (int)frmGridSize.Value;
			}
		}

		private void menuItemShowGrid_Click(object sender, System.EventArgs e)
		{
			menuItemShowGrid.Checked = !menuItemShowGrid.Checked;
			shapeDesigner1.ShowGrid = menuItemShowGrid.Checked;
		}

		private void menuItemSettings_Popup(object sender, System.EventArgs e)
		{
			// ShowGrid could be changed by the context menu
			// update with current state
			menuItemShowGrid.Checked = shapeDesigner1.ShowGrid;
		}

		private void menuItemSave_Click(object sender, System.EventArgs e)
		{
			SaveFileDialog sd = new SaveFileDialog();
			sd.InitialDirectory = ".";
			sd.Filter = FILE_FILTER;
			if (sd.ShowDialog(this) == DialogResult.OK)
			{
				ShapeLibrary lib = new ShapeLibrary(shapeListBox1.Shapes);
				lib.SaveToXml(sd.FileName);
			}
			sd.Dispose();
		}

		private void menuItemOpenLibrary_Click(object sender, System.EventArgs e)
		{
			using (OpenFileDialog fd = new OpenFileDialog())
			{
				fd.Filter = FILE_FILTER;
				if (fd.ShowDialog(this) == DialogResult.OK)
				{
					ShapeLibrary lib = ShapeLibrary.LoadFrom(fd.FileName);
					shapeListBox1.Shapes = lib.Shapes;
					if (shapeListBox1.ShapeCount > 0)
						shapeListBox1.SelectedIndex = 0;
				}
			}
		}

		private void MainForm_Load(object sender, System.EventArgs e)
		{
			shapeListBox1.ShapeSelected += shapeListBox1_ShapeSelected;
			if (shapeListBox1.ShapeCount > 0)
				shapeListBox1.SelectedIndex = 0;

			splitter1.Left = shapeDesigner1.Width = (panel2.Width - shapeListBox1.Width) / 2;
		}

		private void shapeListBox1_ShapeSelected(object sender, ShapeEventArgs e)
		{
			if (e.Shape != null)
				shapeDesigner1.Shape = e.Shape;
		}

		private void shapeDesigner1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			statusBar1.Text = new PointF(
				shapeDesigner1.ClientToShapeX(e.X),
				shapeDesigner1.ClientToShapeY(e.Y)).ToString();
		}

		private void menuItemNewLibrary_Click(object sender, System.EventArgs e)
		{
			newLibrary();
			CreateNewShape();
		}

		private void newLibrary()
		{
			shapeListBox1.ClearShapes();
		}

		private void menuItemNewShape_Click(object sender, System.EventArgs e)
		{
			CreateNewShape();
		}

		public void CreateNewShape()
		{
			Shape newShape = (Shape)Shape.FromId("Rectangle").Clone();
			newShape.Id = "newShape" + ++shapeCounter;
			shapeListBox1.AddShape(newShape);
			shapeListBox1.SelectedIndex = shapeListBox1.ShapeCount - 1;
		}

		private void menuItemDeleteShape_Click(object sender, System.EventArgs e)
		{
			shapeListBox1.RemoveShapeAt(shapeListBox1.SelectedIndex);
		}

		private void shapeListBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			int i = shapeListBox1.IndexFromPoint(e.X, e.Y);

			if (e.Button != MouseButtons.Right) return;

			if (i == ListBox.NoMatches) return;

			// there is a bug in IndexFromPoint when ShapeCount == 0
			// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=116629
			if (shapeListBox1.ShapeCount == 0) return;

			if (i != shapeListBox1.SelectedIndex)
			{
				shapeListBox1.SelectedIndex = i;
			}
			//Point menuLocation = shapeListBox1.PointToClient(new Point(e.X, e.Y));
			Point menuLocation = new Point(e.X, e.Y);
			contextMenuForListBox.Show(shapeListBox1, menuLocation);
		}

		private void menuItemClone_Click(object sender, System.EventArgs e)
		{
			Shape s = shapeListBox1.GetShapeAt(shapeListBox1.SelectedIndex);
			string srcId = s.Id;
			s = (Shape)s.Clone();
			s.Id = srcId;
			shapeListBox1.InsertShape(shapeListBox1.SelectedIndex + 1, s);
			//shapeListBox1.SelectedIndex = ;
		}

		private void menuItemRename_Click(object sender, System.EventArgs e)
		{
			shapeListBox1.StartInlineEdit();
		}

		private void menuItemInsertImage_Click(object sender, System.EventArgs e)
		{
			OpenFileDialog d = new OpenFileDialog();
			d.InitialDirectory = ".";
			if (d.ShowDialog() == DialogResult.OK)
			{
				shapeDesigner1.ImageLocation = d.FileName;
			}
			d.Dispose();
		}

		private void shapeListBox1_ShapeRemoved(object sender, ShapeEventArgs e)
		{
			Debug.WriteLine("shapeListBox1_ShapeRemoved: " + e);
		}

		Rectangle MoveInto(Rectangle child, Rectangle parent)
		{
			child.X = Math.Min(child.X, parent.Right - child.Width);
			child.X = Math.Max(0, child.X);
			child.Y = Math.Min(child.Y, parent.Bottom - child.Height);
			child.Y = Math.Max(0, child.Y);
			//			if (parent.Right < child.Right)
			//				child.X = parent.Right - child.Width;
			return child;
		}

		private void menuItemProperties_Click(object sender, System.EventArgs e)
		{
			PropertiesForm p = new PropertiesForm();

			p.StartPosition = FormStartPosition.Manual;
			p.Left = shapeListBox1.Left - p.Width;
			Rectangle r = shapeListBox1.GetItemRectangle(shapeListBox1.SelectedIndex);
			p.Top = r.Bottom - p.Height;
			p.Bounds = MoveInto(p.Bounds, ClientRectangle);

			p.Location = PointToScreen(p.Location);

			Shape sh = shapeListBox1.Shapes[shapeListBox1.SelectedIndex];
			p.Shape = sh;

			if (p.ShowDialog(this) == DialogResult.OK)
			{
				sh.DisplayName = p.DisplayName;
				sh.Id = p.Id;
			}
		}


		private const string FILE_FILTER = "Shape Library files (*.shl)|*.shl|All Files (*.*)|*.*";

		private Settings settings;
		private int shapeCounter = 0;
	}
}
