using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Resources;
using System.IO;

using CategoryTheory;

namespace DiagramUI
{
	/// <summary>
	/// Summary description for DefaultForm.
	/// </summary>
	public class DefaultForm : System.Windows.Forms.Form, IUpdatableForm
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		static private Dictionary<string, string> resources = new Dictionary<string, string>();
        static private Dictionary<string, string> errorResources = new Dictionary<string, string>();
		private System.ComponentModel.Container components = null;
		private System.Windows.Forms.Button buttonRemove;
		private System.Windows.Forms.PictureBox pictureBoxObject;
		private System.Windows.Forms.Button buttonUpdate;
		private System.Windows.Forms.Label labelSourceH;
		private System.Windows.Forms.PictureBox pictureBoxSource;
		private System.Windows.Forms.Label labelTargetH;
		private System.Windows.Forms.PictureBox pictureBoxTarget;
		private System.Windows.Forms.Label labelSource;
		private System.Windows.Forms.Label labelTarget;
		private System.Windows.Forms.CheckBox checkBoxUpdatable;
		private System.Windows.Forms.Label labelH;

		private INamedComponent component;
		static private string currentDirectory;


		static public string CurrentDirectory
		{
			get
			{
				return currentDirectory;
			}
			set
			{
				currentDirectory = value;
			}
		}

		public static Dictionary<string,string> Resources
		{
			set
			{
				resources = value;
			}
			get
			{
				return resources;
			}
		}

		
		public static Dictionary<string, string> ErrorResources
		{
			set
			{
				errorResources = value;
			}
			get
			{
				return errorResources;
			}
		}

		public static void LoadErrorResources(string filename)
		{
			Stream stream = File.OpenRead(filename);
			ResourceReader rr = new ResourceReader(stream);
			ResourceSet rs = new ResourceSet(rr);
			IDictionaryEnumerator de = rs.GetEnumerator();
			while (de.MoveNext())
			{
				object k = de.Key;
				object v = de.Value;
				errorResources[k + ""] = v + "";
			}
			stream.Close();
		}

		public DefaultForm(INamedComponent component)
		{
			InitializeComponent();
			this.component = component;
			ResourceService.Resources.LoadControlResources(this);//, Resources);
			UpdateFormUI();
			pictureBoxObject.Image = NamedComponent.GetImage(component);
			labelH.Text = NamedComponent.GetToolTip(component);
			object o = null;
			if (component is IObjectLabel)
			{
				IObjectLabel l = component as IObjectLabel;
				o = l.Object;
			}
			if (component is IArrowLabel)
			{
				IArrowLabel l = component as IArrowLabel;
				o = l.Arrow;
			}
			if (!(o is IUpdatableObject))
			{
				checkBoxUpdatable.Visible = false;
			}
			else
			{
				IUpdatableObject upd = o as IUpdatableObject;
				if (upd.ShouldUpdate)
				{
					checkBoxUpdatable.Checked = true;
				}
			}

			if (!(component is IArrowLabel))
			{
				this.labelSourceH.Visible = false;
				this.labelTargetH.Visible = false;
				return;
			}
			IArrowLabel label = component as ArrowLabel;
			pictureBoxSource.Image = NamedComponent.GetImage(label.Source);
			pictureBoxTarget.Image = NamedComponent.GetImage(label.Target);
		}

		/// <summary>
		/// Gets parent form of control
		/// </summary>
		/// <param name="control">The control</param>
		/// <returns>The form</returns>
		public static Form GetParentForm(Control control)
		{
			if (control is Form)
			{
				return control as Form;
			}
			return GetParentForm(control.Parent);
		}

		/// <summary>
		/// Updates form UI
		/// </summary>
		public void UpdateFormUI()
		{
			Text = component.RootName;//NamedComponent.GetText(component) + "";
			if (!(component is IArrowLabel))
			{
				return;
			}
			IArrowLabel label = component as IArrowLabel;
			this.labelSource.Text = label.Source.RootName;//NamedComponent.GetText(label.Source) + "";
			this.labelTarget.Text = label.Target.RootName;//NamedComponent.GetText(label.Target) + "";
		}

		public static void ShowError(Form form, Exception e, Dictionary<string, string> r)
		{
			string message = e.Message;
			string url = null;
			if (e is INamedObject)
			{
				INamedObject n = e as INamedObject;
				url = n.Name;
			}
			if (url == null)
			{
				if (errorResources != null)
				{
                    string s = message;
                    if (errorResources.ContainsKey(message))
                    {
                        s = errorResources[message];
                    }
					if (s != null)
					{
						url = s;
					}
					else
					{
						int n = message.Length;
						IDictionaryEnumerator en = resources.GetEnumerator();
						en.Reset();
						while (en.MoveNext())
						{
							string key = en.Key as string;
							string val = en.Value as string;
							if (val.Length <= n)
							{
								if (message.Substring(0, val.Length).Equals(val))
								{
									s =  errorResources[key] as string;
									if (s != null)
									{
										url = s;
										break;
									}
								}
							}
						}
					}
				}
			}
			string path = null;
			Stream stream = null;
			FormHelp f = null;
			if (r != null)
			{
                string rMessage = message;
                if (r.ContainsKey(message))
                {
                    rMessage = r[message] as string;
                }
				if (rMessage != null)
				{
					message = rMessage;

				}
				else
				{
					if (url != null)
					{
						string filename = url;
						try
						{
							path = currentDirectory + "Help\\" + filename;
							stream = File.OpenRead(path);
							stream.Close();
							f = new FormHelp(message, e, path);
							f.Left = form.Left + form.Width / 2 - f.Width / 2;
							f.Top = form.Top + form.Width / 2 - f.Width / 2;
							f.ShowDialog(form);
							return;
						}
						catch (Exception)
						{
						}
					}
					if (message.Equals(e.Message))
					{
						path = currentDirectory + "Help\\SystemError.htm";
						try
						{
							stream = File.OpenRead(path);
							stream.Close();
						}
						catch (Exception)
						{
						}
                        try
                        {
                            message = (r["System error : "] as string) + message + (r[" contact developer"] as string);
                            f = new FormHelp(message, e, path);
                            f.Left = form.Left + form.Width / 2 - f.Width / 2;
                            f.Top = form.Top + form.Width / 2 - f.Width / 2;
                            f.ShowDialog(form);
                            return;
                        }
                        catch (Exception)
                        {
                        }
                        return;
					}
				}
			}
			if (url!= null)
			{
				string filename = url;
				try
				{
					path = currentDirectory + "Help\\" + filename;
					stream = File.OpenRead(path);
					stream.Close();
					f = new FormHelp(message, e, path);
					f.Left = form.Left + form.Width / 2 - f.Width / 2;
					f.Top = form.Top + form.Width / 2 - f.Width / 2;
					f.ShowDialog(form);
					return;
				}
				catch (Exception ex)
				{
					ex = ex;
				}
			}
			f = new FormHelp(message, e, null);
            if (form != null)
            {
                f.Left = form.Left + form.Width / 2 - f.Width / 2;
                f.Top = form.Top + form.Width / 2 - f.Width / 2;
            }
			f.ShowDialog(form);
			return;
		}


		public static void ShowError(Form form, Exception e, string helpstring, Dictionary<string, string> r)
		{
			string message = e.Message;
			if (r != null)
			{
				string rMessage = r[message];
				if (rMessage != null)
				{
					message = rMessage;
				}
				else
				{
					message = r["System error : "] + message + r[" contact developer"];
				}
			}
			MessageBox.Show(form, message, PanelDesktop.GetResourceString("Error", r), MessageBoxButtons.OK, MessageBoxIcon.Error);
		}




		public static void ShowError(Form form, Exception e)
		{
			ShowError(form, e, resources);
		}

        public static void FillCombo(ComboBox cb, ICollection<string> list)
        {
            cb.Items.Clear();
            foreach (string s in list)
            {
                cb.Items.Add(s);
            }
        }

        public static void FillCombo(ComboBox[] combo, ICollection<string> list)
        {
            foreach (ComboBox cb in combo)
            {
                FillCombo(cb, list);
            }
        }
        public static void FillCombo(IBoxArray boxes, ICollection<string> list)
        {
            ComboBox[] combo = boxes.Boxes;
            FillCombo(combo, list);
        }

       
        public static void FillCombo(ICollection<ComboBox> combo, ICollection<string> list)
        {
            foreach (ComboBox cb in combo)
            {
                FillCombo(cb, list);
            }
        }

        public static void FillCombo(ComboBox box, string str)
        {
            box.Items.Clear();
            foreach (char c in str)
            {
                box.Items.Add(c + "");
            }
        }

        public static void FillCombo(ComboBox box, int min, int max)
        {
            box.Items.Clear();
            for (int i = min; i <= max; i++)
            {
                box.Items.Add(i + "");
            }
        }

 
        public static void FillCombo(ToolStripComboBox box, int min, int max)
        {
            box.Items.Clear();
            for (int i = min; i <= max; i++)
            {
                box.Items.Add(i + "");
            }
        }


        public static void FillCombo(ToolStripComboBox box, List<string> list)
        {
            box.Items.Clear();
            foreach (string s in list)
            {
                box.Items.Add(s);
            }
        }

        public static void FillCombo(ComboBox cb, string[] list)
        {
            cb.Items.Clear();
            foreach (string s in list)
            {
                cb.Items.Add(s);
            }
        }

        public static void FillCheckBox(CheckedListBox box, List<string> list)
        {
            box.Items.Clear();
            foreach (string s in list)
            {
                box.Items.Add(s);
            }
        }
  
        public static void FillCheckBox(CheckedListBox box, string str)
        {
            box.Items.Clear();
            foreach (char c in str)
            {
                box.Items.Add(c + "");
            }
        }

        public static void SelectCombo(ComboBox cb, string item)
        {
            for (int i = 0; i < cb.Items.Count; i++)
            {
                if (cb.Items[i].ToString().Equals(item))
                {
                    cb.SelectedIndex = i;
                    return;
                }
            }
        }

        public static void SelectCombo(ComboBox[] cb, string[] items)
        {
            if (cb.Length != items.Length)
            {
                return;
            }
            for (int i = 0; i < cb.Length; i++)
            {
                SelectCombo(cb[i], items[i]);
            }
        }

        public static void SelectCombo(ComboBox[] cb, List<string> items)
        {
            if (cb.Length != items.Count)
            {
                return;
            }
            for (int i = 0; i < cb.Length; i++)
            {
                SelectCombo(cb[i], items[i]);
            }
        }
        public static void SelectCombo(IBoxArray boxes, List<string> items)
        {
            ComboBox[] cb = boxes.Boxes;
            SelectCombo(cb, items);
         }

        public static List<string> GetSelected(ComboBox[] combo)
        {
            List<string> l = new List<string>();
            for (int i = 0; i < combo.Length; i++)
            {
                string s = combo[i].SelectedItem + "";
                if (s.Length > 0)
                {
                    l.Add(s);
                }
            }
            return l;
        }

        public static List<string> GetSelected(IBoxArray combo)
        {
            ComboBox[] cb = combo.Boxes;
            return GetSelected(cb);
        }


        public static List<string> GetItems(ComboBox box)
        {
            List<string> l = new List<string>();
            foreach (object o in box.Items)
            {
                l.Add(o + "");
            }
            return l;
        }

        public static void AddItem(ComboBox box, string item)
        {
            foreach (object o in box.Items)
            {
                if (item.Equals(o + ""))
                {
                    return;
                }
            }
            box.Items.Add(item);
        }


        public static void AddItem(ComboBox box)
        {
            AddItem(box, box.Text);
        }

        public static void RemoveSelected(ComboBox box)
        {
            if (box.SelectedItem == null)
            {
                return;
            }
            object o = box.SelectedItem;
            box.Items.Remove(o);
        }


        public static void SelectCombo(ComboBox box, char c)
        {
            for (int i = 0; i < box.Items.Count; i++)
            {
                if (box.Items[i].ToString().Equals(c + ""))
                {
                    box.SelectedIndex = i;
                    return;
                }
            }
        }


 

        public static void SelectCombo(ToolStripComboBox cb, string item)
        {
            for (int i = 0; i < cb.Items.Count; i++)
            {
                if (cb.Items[i].ToString().Equals(item))
                {
                    cb.SelectedIndex = i;
                    return;
                }
            }
        }

        public static void CheckList(CheckedListBox box, ICollection<string> list)
        {
            box.Items.Clear();
            foreach (string s in list)
            {
                box.Items.Add(s);
            }
        }


        public static void CheckList(CheckedListBox box, ICollection<string> list, ICollection<string> check)
        {
            box.Items.Clear();
            foreach (string s in list)
            {
                if (check.Contains(s))
                {
                    box.Items.Add(s, CheckState.Checked);
                }
                else
                {
                    box.Items.Add(s, CheckState.Unchecked);
                }
            }
        }

        public static void CheckList(CheckedListBox box, string str)
        {
            box.Items.Clear();
            foreach (char c in str)
            {
                box.Items.Add(c + "");
            }
        }

        public static void CheckList(CheckedListBox box, string str, string check)
        {
            box.Items.Clear();
            foreach (char c in str)
            {
                if (check.IndexOf(c) >= 0)
                {
                    box.Items.Add(c + "", CheckState.Checked);
                }
                else
                {
                    box.Items.Add(c + "", CheckState.Unchecked);
                }
            }
        }


        public static List<string> GetChecked(CheckedListBox box)
        {
            List<string> l = new List<string>();
            foreach (string s in box.CheckedItems)
            {
                l.Add(s);
            }
            return l;
        }
        
        public static List<string> GetUnchecked(CheckedListBox box)
        {
            List<string> l = new List<string>();
            List<string> check = GetChecked(box);
            foreach (string s in box.Items)
            {
                if (!check.Contains(s))
                {
                    l.Add(s);
                }
            }
            return l;
        }


        public static string GetCheckedString(CheckedListBox box)
        {
            string str = "";
            foreach (string s in box.CheckedItems)
            {
                str += s[0];
            }
            return str;
        }
       
        public static string GetUncheckedString(CheckedListBox box)
        {
            string str = "";
            string check = GetCheckedString(box);
            foreach (string s in box.Items)
            {
                char c = s[0];
                if (check.IndexOf(c) < 0)
                {
                    str += c;
                }
            }
            return str;
        }


        public static void FillListBox(ListBox box, ICollection<string> items)
        {
            foreach (string item in items)
            {
                box.Items.Add(item);
            }
        }

       



        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		//	NamedComponent.RemoveForm(component);
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.buttonRemove = new System.Windows.Forms.Button();
			this.pictureBoxObject = new System.Windows.Forms.PictureBox();
			this.buttonUpdate = new System.Windows.Forms.Button();
			this.labelSourceH = new System.Windows.Forms.Label();
			this.pictureBoxSource = new System.Windows.Forms.PictureBox();
			this.labelTargetH = new System.Windows.Forms.Label();
			this.pictureBoxTarget = new System.Windows.Forms.PictureBox();
			this.labelSource = new System.Windows.Forms.Label();
			this.labelTarget = new System.Windows.Forms.Label();
			this.checkBoxUpdatable = new System.Windows.Forms.CheckBox();
			this.labelH = new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// buttonRemove
			// 
			this.buttonRemove.Location = new System.Drawing.Point(344, 112);
			this.buttonRemove.Name = "buttonRemove";
			this.buttonRemove.TabIndex = 0;
			this.buttonRemove.Text = "Remove";
			this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click);
			// 
			// pictureBoxObject
			// 
			this.pictureBoxObject.Location = new System.Drawing.Point(8, 8);
			this.pictureBoxObject.Name = "pictureBoxObject";
			this.pictureBoxObject.Size = new System.Drawing.Size(40, 40);
			this.pictureBoxObject.TabIndex = 1;
			this.pictureBoxObject.TabStop = false;
			// 
			// buttonUpdate
			// 
			this.buttonUpdate.Location = new System.Drawing.Point(344, 80);
			this.buttonUpdate.Name = "buttonUpdate";
			this.buttonUpdate.TabIndex = 2;
			this.buttonUpdate.Text = "Update";
			this.buttonUpdate.Click += new System.EventHandler(this.buttonUpdate_Click);
			// 
			// labelSourceH
			// 
			this.labelSourceH.Location = new System.Drawing.Point(64, 112);
			this.labelSourceH.Name = "labelSourceH";
			this.labelSourceH.TabIndex = 3;
			this.labelSourceH.Text = "Source";
			// 
			// pictureBoxSource
			// 
			this.pictureBoxSource.Location = new System.Drawing.Point(32, 152);
			this.pictureBoxSource.Name = "pictureBoxSource";
			this.pictureBoxSource.Size = new System.Drawing.Size(32, 32);
			this.pictureBoxSource.TabIndex = 4;
			this.pictureBoxSource.TabStop = false;
			// 
			// labelTargetH
			// 
			this.labelTargetH.Location = new System.Drawing.Point(64, 216);
			this.labelTargetH.Name = "labelTargetH";
			this.labelTargetH.TabIndex = 5;
			this.labelTargetH.Text = "Target";
			// 
			// pictureBoxTarget
			// 
			this.pictureBoxTarget.Location = new System.Drawing.Point(32, 256);
			this.pictureBoxTarget.Name = "pictureBoxTarget";
			this.pictureBoxTarget.Size = new System.Drawing.Size(32, 32);
			this.pictureBoxTarget.TabIndex = 6;
			this.pictureBoxTarget.TabStop = false;
			// 
			// labelSource
			// 
			this.labelSource.Location = new System.Drawing.Point(88, 152);
			this.labelSource.Name = "labelSource";
			this.labelSource.Size = new System.Drawing.Size(312, 48);
			this.labelSource.TabIndex = 7;
			// 
			// labelTarget
			// 
			this.labelTarget.Location = new System.Drawing.Point(88, 256);
			this.labelTarget.Name = "labelTarget";
			this.labelTarget.Size = new System.Drawing.Size(312, 56);
			this.labelTarget.TabIndex = 8;
			// 
			// checkBoxUpdatable
			// 
			this.checkBoxUpdatable.Location = new System.Drawing.Point(216, 336);
			this.checkBoxUpdatable.Name = "checkBoxUpdatable";
			this.checkBoxUpdatable.Size = new System.Drawing.Size(192, 32);
			this.checkBoxUpdatable.TabIndex = 9;
			this.checkBoxUpdatable.Text = "Updatable";
			this.checkBoxUpdatable.CheckedChanged += new System.EventHandler(this.checkBoxUpdatable_CheckedChanged);
			// 
			// labelH
			// 
			this.labelH.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.labelH.Location = new System.Drawing.Point(64, 8);
			this.labelH.Name = "labelH";
			this.labelH.Size = new System.Drawing.Size(360, 64);
			this.labelH.TabIndex = 10;
			this.labelH.Text = "labelH";
			// 
			// DefaultForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(440, 389);
			this.Controls.Add(this.labelH);
			this.Controls.Add(this.checkBoxUpdatable);
			this.Controls.Add(this.labelTarget);
			this.Controls.Add(this.labelSource);
			this.Controls.Add(this.pictureBoxTarget);
			this.Controls.Add(this.labelTargetH);
			this.Controls.Add(this.pictureBoxSource);
			this.Controls.Add(this.labelSourceH);
			this.Controls.Add(this.buttonUpdate);
			this.Controls.Add(this.pictureBoxObject);
			this.Controls.Add(this.buttonRemove);
			this.Name = "DefaultForm";
			this.Text = "DefaultForm";
			this.ResumeLayout(false);

		}
		#endregion

		private void loadResources()
		{
			ResourceService.Resources.LoadControlResources(this);

		}
		private void buttonRemove_Click(object sender, System.EventArgs e)
		{
			/*
			if (component is IObjectLabel)
			{
				IObjectLabel lab = component as IObjectLabel;
				lab.Remove(true);
			}
			else if (component is IArrowLabel)
			{
				IArrowLabel lab = component as IArrowLabel;
				lab.Remove(true);
			}
			*/
			//NamedComponent.RemoveForm(component);
			Dispose();
		}

		private void buttonUpdate_Click(object sender, System.EventArgs e)
		{
			try
			{
				if (component is IObjectLabel)
				{
					IObjectLabel lab = component as IObjectLabel;
					ICategoryObject obj = lab.Object;
					if (obj is IUpdatableObject)
					{
						IUpdatableObject updatable = obj as IUpdatableObject;
						updatable.UpdateObject();
					}
				}
				else if (component is IArrowLabel)
				{
					IArrowLabel lab = component as IArrowLabel;
					ICategoryArrow arrow = lab.Arrow;
					if (arrow is IUpdatableObject)
					{
						IUpdatableObject updatable = arrow as IUpdatableObject;
						updatable.UpdateObject();
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(this, ex.Message);
			}
		}

		private void checkBoxUpdatable_CheckedChanged(object sender, System.EventArgs e)
		{
			object o = null;
			if (component is IObjectLabel)
			{
				IObjectLabel lab = component as IObjectLabel;
				o = lab.Object;
			}
			else if (component is IArrowLabel)
			{
				IArrowLabel lab = component as IArrowLabel;
				o = lab.Arrow;
			}
			if (o is IUpdatableObject)
			{
				IUpdatableObject updatable = o as IUpdatableObject;
				updatable.ShouldUpdate = checkBoxUpdatable.Checked;
			}
		}
	}
}
