using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Windows.Forms;

namespace DiagramUI
{
    /// <summary>
    /// The tools of diagram
    /// </summary>
    public class ToolsDiagram
    {
        /// <summary>
        /// The active button
        /// </summary>
        protected PaletteButton active = null;


        /// <summary>
        /// Table of buttons
        /// </summary>
        protected Hashtable buttonHash = new Hashtable();

        /// <summary>
        /// The button on click event handler
        /// </summary>
        private ToolBarButtonClickEventHandler handler;

        /// <summary>
        /// The UI factory
        /// </summary>
        private IUIFactory factory;

        /// <summary>
        /// The buttons
        /// </summary>
        private ArrayList buttons;


        /// <summary>
        /// Image list of buttons
        /// </summary>
        private ImageList buttonImages = new ImageList();

        /// <summary>
        /// The tree view
        /// </summary>
        private TreeView tree;

        /// <summary>
        /// Objects node
        /// </summary>
        private TreeNode objectsNode;


        /// <summary>
        /// Arrows node;
        /// </summary>
        private TreeNode arrowsNode;


        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="factory">The UI factory</param>
        public ToolsDiagram(IUIFactory factory)
        {
            handler = new ToolBarButtonClickEventHandler(this.ToolBar_ButtonClick);
            this.factory = factory;
            factory.Tools = this;
            buttons = new ArrayList();
        }


        /// <summary>
        /// The tree view
        /// </summary>
        public TreeView Tree
        {
            get
            {
                return tree;
            }
            set
            {
                tree = value;
                tree.ImageList = buttonImages;
                objectsNode = new TreeNode(ResourceService.Resources.GetResourceString("Objects"));
                arrowsNode = new TreeNode(ResourceService.Resources.GetResourceString("Arrows"));
                objectsNode.ImageIndex = 0;
                arrowsNode.ImageIndex = 1;
                arrowsNode.SelectedImageIndex = 1;
                tree.Nodes.Add(objectsNode);
                tree.Nodes.Add(arrowsNode);
                tree.MouseUp += new MouseEventHandler(treeUp);
                tree.AfterLabelEdit += new System.Windows.Forms.NodeLabelEditEventHandler(editNode);
                tree.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(selectTree);
                tree.LabelEdit = true;
            }
        }

        /// <summary>
        /// Edit tree node event handler
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        private void editNode(object sender, System.Windows.Forms.NodeLabelEditEventArgs e)
        {
            string name = e.Label;
            if (!(e.Node is NamedNode))
            {
                return;
            }
            NamedNode node = e.Node as NamedNode;
            node.SetName(name);
        }


        /// <summary>
        /// Select event handler
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        private void selectTree(object sender, System.Windows.Forms.TreeViewEventArgs e)
        {

            if (!(e.Node is NamedNode))
            {
                return;
            }
            NamedNode node = e.Node as NamedNode;
        }



        /// <summary>
        /// Tree mouse up event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Right)
            {
                return;
            }
            TreeNode n = tree.SelectedNode;
            if (!(n is NamedNode))
            {
                return;
            }
            NamedNode node = n as NamedNode;
            node.ShowForm();
        }

        /// <summary>
        /// Adds tree node to object label
        /// </summary>
        /// <param name="label">The object label</param>
        private void addObjectNode(TreeNode parent, IObjectLabel label)
        {
            if (tree == null)
            {
                return;
            }
            NamedNode node = new NamedNode(label, false);
            if (label is ObjectLabel)
            {
                ObjectLabel lab = label as ObjectLabel;
                lab.Node = node;
            }
            parent.Nodes.Add(node);
            if (!(label.Object is ObjectContainer))
            {
                return;
            }
            ObjectContainer cont = label.Object as ObjectContainer;
            IDesktop desk = cont.Desktop;
            Hashtable t = cont.Interface;
            foreach (string str in t.Keys)
            {
                INamedComponent comp = desk[str];
                NamedNode n = new NamedNode(comp, false);
                node.Nodes.Add(n);
            }
        }


        public void AddObjectNode(ObjectLabel label)
        {
            addObjectNode(objectsNode, label);
        }

        /// <summary>
        /// Adds arrow node
        /// </summary>
        /// <param name="label"></param>
        public void AddArrowNode(ArrowLabel label)
        {
            if (tree == null)
            {
                return;
            }
            NamedNode node = new NamedNode(label, false);
            label.Node = node;
            arrowsNode.Nodes.Add(node);
            NamedNode ns = new NamedNode(label.Source, true);
            node.Nodes.Add(ns);
            NamedNode nt = new NamedNode(label.Target, true);
            node.Nodes.Add(nt);
        }
        /// <summary>
        /// Removes object node
        /// </summary>
        /// <param name="label">The object label</param>
        public void RemoveObjectNode(ObjectLabel label)
        {
            if (tree == null)
            {
                return;
            }
            try
            {
                objectsNode.Nodes.Remove(label.Node);
            }
            catch (Exception)
            {
            }
        }


        /// <summary>
        /// Removes arrow node
        /// </summary>
        /// <param name="label">The arrow label</param>
        public void RemoveArrowNode(ArrowLabel label)
        {
            if (tree == null)
            {
                return;
            }
            arrowsNode.Nodes.Remove(label.Node);
        }




        /// <summary>
        /// The "on click" event handler
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event handler arguments</param>
        protected void ToolBar_ButtonClick(Object sender, ToolBarButtonClickEventArgs e)
        {
            PaletteButton but = (PaletteButton)e.Button;
            if (active != but)
            {
                if (active != null)
                {
                    active.Pushed = false;
                }
                active = but;
            }
        }

        public int Count
        {
            get
            {
                return buttonImages.Images.Count;
            }
        }

        /// <summary>
        /// The active button
        /// </summary>
        public PaletteButton Active
        {
            get
            {
                return active;
            }
        }

        /// <summary>
        /// The "on click" event handler
        /// </summary>
        public ToolBarButtonClickEventHandler ClickEventHandler
        {
            get
            {
                return handler;
            }
        }

        /// <summary>
        /// The UI factory
        /// </summary>
        public IUIFactory Factory
        {
            get
            {
                return factory;
            }
        }

        /// <summary>
        /// Adds button to this panel
        /// </summary>
        /// <param name="button">The button to add</param>
        public void AddButton(PaletteButton button)
        {
            buttons.Add(button);
            buttonImages.Images.Add(button.ButtonImage);
            Hashtable t = null;
            string kind = button.StringKind;
            if (kind == null)
            {
                return;
            }
            if (buttonHash.Contains(kind))
            {
                t = buttonHash[kind] as Hashtable;
            }
            else
            {
                t = new Hashtable();
                buttonHash[kind] = t;
            }
            t[button.Type] = button;
        }

        /// <summary>
        /// Finds required button
        /// </summary>
        /// <param name="kind">The button kind</param>
        /// <param name="type">The button type</param>
        /// <returns>The required button</returns>
        public PaletteButton FindButton(INamedComponent nc)
        {
            //factory
            if (nc is NamedComponent)
            {
                NamedComponent named = nc as NamedComponent;
                object[] bs = buttons.ToArray();
                if (named.Kind >= 0)
                {
                    for (int i = 0; i < bs.Length; i++)
                    {
                        PaletteButton b = bs[i] as PaletteButton;
                        if (b.Kind >= 0)
                        {
                            if ((b.Kind == named.Kind) & (b.Type.Equals(named.Type)))
                            {
                                return b;
                            }
                        }
                    }
                }
            }
            if (buttonHash.ContainsKey(nc.Kind))
            {
                Hashtable t = buttonHash[nc.Kind] as Hashtable;
                if (t.Contains(nc.Type))
                {
                    return t[nc.Type] as PaletteButton;
                }
            }
            return null;
        }

        public PaletteButton FindButton(string kind, string type)
        {
            if (buttonHash.ContainsKey(kind))
            {
                Hashtable t = buttonHash[kind] as Hashtable;
                if (t.Contains(type))
                {
                    return t[type] as PaletteButton;
                }
            }
            return null;
        }


        /// <summary>
        /// Createa Object editor form of property editor object
        /// </summary>
        /// <param name="obj">The property editor ofject</param>
        /// <returns>The property editor form</returns>
        static public Form CreateEditorForm(object obj)
        {
            if (obj is IPropertiesEditor)
            {
                IPropertiesEditor pe = obj as IPropertiesEditor;
                object ob = pe.Editor;
                if (ob != null)
                {
                    if (ob is Form)
                    {
                        Form f = ob as Form;
                        return f;
                    }
                    if (ob is Array)
                    {
                        Array arr = ob as Array;
                        object h = arr.GetValue(0);
                        if (h is Form)
                        {
                            Form f = h as Form;
                            return f;
                        }
                    }
                }

            }
            if (obj is MultiLibraryObject)
            {
                MultiLibraryObject mo = obj as MultiLibraryObject;
                IObjectLabel lab = mo.Object as IObjectLabel;
                return new FormMultilibrary(lab);
            }
            return null;
        }
    }
}
