using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using MySQL.Grt;
using MySQL.Grt.Db;
using MySQL.Utilities;

namespace MySQL.GUI.Workbench.Plugins
{
  class DbMysqlTableFkColumnListModel : GrtListModel
  {
    private NodeCheckBox columnEnabledFkNodeControl;
    private AdvNodeTextBox nameNodeControl;
    private AdvNodeComboBox targetColumnNodeControl;
    private MySQLTableEditorBE mySQLTableEditorBE;

		/// <summary>
		/// Constructor that initializes the model with the given objects
		/// </summary>
		/// <param name="TreeView">The TreeViewAdv control this model belongs to</param>
		/// <param name="GrtTree">The GRT tree this model belongs to</param>
		/// <param name="NodeStateIcon">The NodeStateIcon NodeControl that displays the icon</param>
    public DbMysqlTableFkColumnListModel(TreeViewAdv ListView, FKConstraintColumnsListBE GrtList,
      NodeCheckBox ColumnEnabledFkNodeControl, AdvNodeTextBox NameNodeControl, 
      AdvNodeComboBox TargetNodeControl, MySQLTableEditorBE MySQLTableEditorBE)
			: base(ListView, GrtList)
		{
      columnEnabledFkNodeControl = ColumnEnabledFkNodeControl;
			nameNodeControl = NameNodeControl;
      targetColumnNodeControl = TargetNodeControl;
      mySQLTableEditorBE = MySQLTableEditorBE;

			// assign virtual value events for displaying and processing the edited value content
      columnEnabledFkNodeControl.CheckStateChanged += new EventHandler<TreePathEventArgs>(columnEnabledFkNodeControl_CheckStateChanged);
      columnEnabledFkNodeControl.ValueNeeded += new EventHandler<NodeControlValueEventArgs>(ValueNeeded);
      columnEnabledFkNodeControl.ValuePushed += new EventHandler<NodeControlValueEventArgs>(ValuePushed);
			nameNodeControl.EditorInitialize += new EditorInitializeEventHandler(EditorInitialize);
			nameNodeControl.ValueNeeded += new EventHandler<NodeControlValueEventArgs>(ValueNeeded);
			nameNodeControl.ValuePushed += new EventHandler<NodeControlValueEventArgs>(ValuePushed);
      targetColumnNodeControl.EditorInitialize += new EditorInitializeEventHandler(EditorInitialize);
      targetColumnNodeControl.ValueNeeded += new EventHandler<NodeControlValueEventArgs>(ValueNeeded);
      targetColumnNodeControl.ValuePushed += new EventHandler<NodeControlValueEventArgs>(ValuePushed);
		}

    public override void DetachEvents()
    {
      base.DetachEvents();

      // remove virtual value events
      columnEnabledFkNodeControl.ValueNeeded -= ValueNeeded;
      columnEnabledFkNodeControl.ValuePushed -= ValuePushed;

      nameNodeControl.EditorInitialize -= EditorInitialize;
      nameNodeControl.ValueNeeded -= ValueNeeded;
      nameNodeControl.ValuePushed -= ValuePushed;

      targetColumnNodeControl.EditorInitialize -= EditorInitialize;
      targetColumnNodeControl.ValueNeeded -= ValueNeeded;
      targetColumnNodeControl.ValuePushed -= ValuePushed;
    }

    /// <summary>
    /// Returns a node list of all child nodes of a given parent node
    /// </summary>
    /// <param name="treePath">The path of the parent node</param>
    /// <returns>The list of child nodes for the given parent path node</returns>
    public override System.Collections.IEnumerable GetChildren(TreePath treePath)
    {
      List<GrtListNode> items = new List<GrtListNode>();

      int count = grtList.count();
      for (int i = 0; i < count; i++)
      {
        NodeId nodeId = grtList.get_node(i);
        GrtListNode node;
        string caption;

        grtList.get_field(nodeId, 0, out caption);

        node = new GrtListNode(null, nodeId, null, this);

        items.Add(node);
      }
      return items;
    }

    #region event handlers
    /// <summary>
    /// Event handler that gets the caption for the value column
    /// </summary>
    /// <param name="sender">The object triggering the event</param>
    /// <param name="e">The event parameter</param>
    private void ValueNeeded(object sender, NodeControlValueEventArgs e)
    {
      if (e.Node != null && e.Node.Tag != null)
      {
        GrtListNode node = e.Node.Tag as GrtListNode;

        if (node != null)
        {
          if (sender == columnEnabledFkNodeControl)
          {
            e.Value = ((FKConstraintColumnsListBE)grtList).get_column_is_fk(node.NodeId);
          }
          else if (sender == nameNodeControl)
          {
            string caption;

            grtList.get_field(node.NodeId, (int)FKConstraintColumnsListBE.FKConstraintColumnsListColumns.Column, out caption);

            e.Value = caption;
          }
          else if (sender == targetColumnNodeControl)
          {
            string caption;

            grtList.get_field(node.NodeId, (int)FKConstraintColumnsListBE.FKConstraintColumnsListColumns.RefColumn, out caption);

            e.Value = caption;
          }
        }
      }
    }

    /// <summary>
    /// Event handler that sets the new value for the value column
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ValuePushed(object sender, NodeControlValueEventArgs e)
    {
      if (e.Node != null && e.Node.Tag != null)
      {
        GrtListNode node = e.Node.Tag as GrtListNode;

        if (node != null)
        {
          if (sender == columnEnabledFkNodeControl)
          {
            ((FKConstraintColumnsListBE)grtList).set_column_is_fk(node.NodeId, (CheckState)e.Value == CheckState.Checked);
          }
          else if (sender == nameNodeControl)
          {
            String value = e.Value as String;
            if (value != null)
              grtList.set_field(node.NodeId, (int)FKConstraintColumnsListBE.FKConstraintColumnsListColumns.Column, e.Value as String);
          }
          else if (sender == targetColumnNodeControl)
          {
            String value = e.Value as String;
            if (value != null)
              grtList.set_field(node.NodeId, (int)FKConstraintColumnsListBE.FKConstraintColumnsListColumns.RefColumn, e.Value as String);
          }

          RefreshModel();
        }
      }
    }

    private void EditorInitialize(object sender, EditorInitializeEventArgs e)
    {
      if (sender == nameNodeControl)
      {
        TextBox textBox = e.Editor as TextBox;
        if (textBox != null)
        {
          if (ListView.CurrentNode.Index == 0)
            textBox.Text = "id" + mySQLTableEditorBE.get_name();

          textBox.KeyDown += new KeyEventHandler(textBox_KeyDown);
        }
      }
      else if (sender == targetColumnNodeControl)
      {
        ComboBox comboBox = e.Editor as ComboBox;
        if (comboBox != null)
          comboBox.KeyDown += new KeyEventHandler(textBox_KeyDown);

        GrtListNode node = listView.CurrentNode.Tag as GrtListNode;

        List<string> columns = ((FKConstraintColumnsListBE)GrtList).get_ref_columns_list(node.NodeId);

        string selected;
        grtList.get_field(node.NodeId, (int)FKConstraintColumnsListBE.FKConstraintColumnsListColumns.RefColumn, out selected);

        comboBox.Items.Clear();
        comboBox.Items.AddRange(columns.ToArray());

        int i= 0;
        foreach (String col in columns)
        {
          if (col == selected)
          {
            comboBox.SelectedIndex = i;
          }
          i++;
        }
      }
    }

    void textBox_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Tab || e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
      {
        Control c = sender as Control;
        if (c != null)
        {
          if (c.Tag == nameNodeControl)
          {
            // Remember current index
            int selIndex = 0;
            if (this.ListView.SelectedNode != null)
              selIndex = this.ListView.SelectedNode.Index;
            TextBox t = c as TextBox;
            string value = "";
            if (t != null)
              value = t.Text;

            nameNodeControl.EndEdit(true);

            // Try to select previous index again
            if (selIndex < this.ListView.Root.Children.Count && value.Length > 0)
            {
              this.ListView.SelectedNode = this.ListView.Root.Children[selIndex];

              targetColumnNodeControl.BeginEdit();
            }
            e.Handled = true;
          }
          else if (c.Tag == targetColumnNodeControl)
          {
            // Remember current index
            int selIndex = 0;
            if (this.ListView.SelectedNode != null)
              selIndex = this.ListView.SelectedNode.Index;
            TextBox t = c as TextBox;
            string value = "";
            if (t != null)
              value = t.Text;

            targetColumnNodeControl.EndEdit(true);

            e.Handled = true;
          }
        }
      }
    }

    void columnEnabledFkNodeControl_CheckStateChanged(object sender, TreePathEventArgs e)
    {
      GrtListNode node = e.Path.LastNode as GrtListNode;

      if (node != null && ((FKConstraintColumnsListBE)grtList).get_column_is_fk(node.NodeId))
      {
        // try to find current column
        try
        {
          foreach (TreeNodeAdv treeNode in ListView.AllNodes)
            if (treeNode.Tag as GrtListNode != null)
            {
              if (node.NodeId.equals((treeNode.Tag as GrtListNode).NodeId))
              {
                if (this.ListView.SelectedNode == treeNode) // fix for refreshing fk list tons of times
                  return;
                this.ListView.SelectedNode = treeNode;
                break;
              }
            }
        }
        catch
        {
          // ignore errors
        }

        targetColumnNodeControl.BeginEdit();
      }
    }


    #endregion

  }
}
