using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using Aga.Controls.Tree;
using MySQL.Grt;
using MySQL.Utilities;
using MySQL.Grt.Db;

namespace MySQL.GUI.Workbench.Plugins
{
  public partial class DbMysqlRoleEditor : ObjectEditorPlugin
  {
    #region Member Variables

    private RoleEditorBE roleEditorBE { get { return editorBE as RoleEditorBE; } } 

    private RoleTreeBE roleTreeBE;
    private SimpleGrtTreeModel roleTreeModel;

    private RoleObjectListBE roleObjectListBE;
    private RolePrivilegeListBE rolePrivilegeListBE;
    private SimpleGrtListModel roleObjectListModel;

    #endregion

    #region Constructors

    protected DbMysqlRoleEditor()
    {
      InitializeComponent();
    }

    public DbMysqlRoleEditor(GrtManager GrtManager, GrtValue GrtList)
      : base(new RoleEditorBE(GrtManager, GrtList))
    {
      InitializeComponent();
      // Init BE
      roleTreeBE = roleEditorBE.get_role_tree();
      roleTreeBE.refresh();

      roleObjectListBE = roleEditorBE.get_object_list();
      roleObjectListBE.refresh();
      rolePrivilegeListBE = roleEditorBE.get_privilege_list();
      rolePrivilegeListBE.refresh();

      InitializingControls = true;
      try
      {
        roleTreeModel = new SimpleGrtTreeModel(rolesTreeView, roleTreeBE);
        roleTreeModel.AddColumn(roleNameNodeControl, (int)RoleTreeBE.Columns.Name, true);
        //roleTreeModel = new DbMysqlRoleTreeModel(rolesTreeView, roleTreeBE, roleNameNodeControl);
        rolesTreeView.Model = roleTreeModel;

        rolesTreeView.ItemDrag += new ItemDragEventHandler(rolesTreeView_ItemDrag);
        rolesTreeView.DragEnter += new DragEventHandler(rolesTreeView_DragEnter);
        rolesTreeView.DragOver += new DragEventHandler(rolesTreeView_DragOver);
        rolesTreeView.DragDrop += new DragEventHandler(rolesTreeView_DragDrop);

        //rolesTreeView.SelectedNode = rolesTreeView.FindNodeByTag(roleTreeModel.FindNodeWithObject(grtObject));

        roleObjectListModel = new SimpleGrtListModel(roleObjectsTreeView, roleObjectListBE);
        roleObjectListModel.AddColumn(objectNameNodeControl, (int)RoleObjectListBE.Columns.Name, false);
        roleObjectsTreeView.Model = roleObjectListModel;


        RefreshPrivilegesList();
      }
      finally
      {
        InitializingControls = false;
      }

      TabText = roleEditorBE.get_name();
    }

    #endregion

    #region IWorkbenchDocument implementation

    public override UIForm BackendClass
    {
      get { return roleEditorBE; }
    }

    #endregion

    #region Form implementation

    void rolesTreeView_DragDrop(object sender, DragEventArgs e)
    {
      TreeNodeAdv[] nodes = (TreeNodeAdv[])e.Data.GetData(typeof(TreeNodeAdv[]));
      TreeNodeAdv dropNode = rolesTreeView.DropPosition.Node;
      if (dropNode == null) return;

      NodeId dropNodeId = ((GrtTreeNode)dropNode.Tag).NodeId;

      if (rolesTreeView.DropPosition.Position == NodePosition.Inside)
      {
        foreach (TreeNodeAdv node in nodes)
        {
          if (node.Equals(dropNode))
            continue;

          NodeId next_id = ((GrtTreeNode)node.Tag).NodeId;
          roleTreeBE.append_child(dropNodeId, next_id);
        }

        roleTreeBE.refresh();

        rolesTreeView.Model = null;
        rolesTreeView.Model = roleTreeModel;
        
        //rolesTreeView.DropPosition.Node.IsExpanded = true;
      }
      else
      {
        foreach (TreeNodeAdv node in nodes)
        {
          NodeId next_id = ((GrtTreeNode)(node.Tag)).NodeId;
          //roleTreeBE.append_child(roleTreeBE.get_parent(dropNodeId), next_id);
          roleTreeBE.move_to_top_level(next_id);
        }

        roleTreeBE.refresh();

        rolesTreeView.Model = null;
        rolesTreeView.Model = roleTreeModel;
      }
    }

    void rolesTreeView_DragOver(object sender, DragEventArgs e)
    {
      e.Effect = DragDropEffects.None;

      if ((rolesTreeView.DropPosition.Position == NodePosition.Inside) && (e.Data.GetDataPresent(typeof(TreeNodeAdv[])) == true))
      {
        e.Effect = DragDropEffects.Move;
      }
      else if (rolesTreeView.DropPosition.Node != null)
      {
        NodeId nid = roleTreeBE.get_parent(((GrtTreeNode)rolesTreeView.DropPosition.Node.Tag).NodeId);
        bool is_root = !nid.is_valid();
        if (is_root)
        {
          bool dragging_non_root = false;
          TreeNodeAdv[] nodes = (TreeNodeAdv[])e.Data.GetData(typeof(TreeNodeAdv[]));

          foreach (TreeNodeAdv node in nodes)
          {
            NodeId next_id = ((GrtTreeNode)node.Tag).NodeId;
            dragging_non_root = roleTreeBE.get_parent(next_id).is_valid();
            if (dragging_non_root)
            {
              e.Effect = DragDropEffects.Move;
              break;
            }
          }
        }
      }
    }

    void rolesTreeView_DragEnter(object sender, DragEventArgs e)
    {
      if ((rolesTreeView.DropPosition.Position == NodePosition.Inside) && (e.Data.GetDataPresent(typeof(TreeNodeAdv[])) == true))
        e.Effect = DragDropEffects.Move;
      else
        e.Effect = DragDropEffects.None;
    }

    void rolesTreeView_ItemDrag(object sender, ItemDragEventArgs e)
    {
      TreeNodeAdv[] nodes = new TreeNodeAdv[rolesTreeView.SelectedNodes.Count];
      rolesTreeView.SelectedNodes.CopyTo(nodes, 0);
      DoDragDrop(nodes, DragDropEffects.Move);
    }

    private void RefreshPrivilegesList()
    {
      privCheckedListBox.Items.Clear();
      
      int count = rolePrivilegeListBE.count();
      String caption;
      int enabled;

      for (int i= 0; i < count; i++)
      {
        rolePrivilegeListBE.get_field(new NodeId(i), (int)RolePrivilegeListBE.Columns.Name, out caption);
        rolePrivilegeListBE.get_field(new NodeId(i), (int)RolePrivilegeListBE.Columns.Enabled, out enabled);
        privCheckedListBox.Items.Add(caption, enabled!=0);
      }
    }

    private void roleObjectsTreeView_SelectionChanged(object sender, EventArgs e)
    {
      if (roleObjectsTreeView.SelectedNode != null)
      {
        GrtListNode activeNode = roleObjectsTreeView.SelectedNode.Tag as GrtListNode;

        roleObjectListBE.set_selected_node(activeNode.NodeId);
        RefreshPrivilegesList();
      }
      else
      {
        roleObjectListBE.set_selected_node(new NodeId());
        RefreshPrivilegesList();
      }
    }

    private void privCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
    {
      rolePrivilegeListBE.set_field(new NodeId(e.Index), (int)RolePrivilegeListBE.Columns.Enabled,
        e.NewValue==CheckState.Checked ? 1: 0);
    }

    private void rolesTreeView_SelectionChanged(object sender, EventArgs e)
    {
      if (rolesTreeView.CurrentNode != null)
      {
        NodeId node = ((GrtTreeNode)(rolesTreeView.CurrentNode.Tag)).NodeId;
        MySQL.Grt.GrtValue grt_object = roleTreeBE.get_role_with_id(node);
        roleEditorBE.set_role(grt_object);

        roleObjectListBE.refresh();
        rolePrivilegeListBE.refresh();

        roleObjectsTreeView.Model = null;
        roleObjectsTreeView.Model = roleObjectListModel;

        RefreshPrivilegesList();
      }
      TabText = roleEditorBE.get_name();
    }

    private void roleObjectsTreeView_DragEnter(object sender, DragEventArgs e)
    {
      if (e.Data.GetDataPresent(typeof(List<GrtValue>)) == true || e.Data.GetDataPresent(typeof(GrtValue))==true)
        e.Effect = DragDropEffects.Copy;
    }

    private void roleObjectsTreeView_DragDrop(object sender, DragEventArgs e)
    {
      if (e.Data.GetDataPresent(typeof(List<GrtValue>)) == true)
      {
        List<GrtValue> selGrtValues = (List<GrtValue>)e.Data.GetData(typeof(List<GrtValue>));
        foreach (GrtValue grtValue in selGrtValues)
        {
          roleEditorBE.add_object(grtValue);
        }
      }
      else if (e.Data.GetDataPresent(typeof(GrtValue))==true)
      {
        GrtValue selGrtValue = (GrtValue)e.Data.GetData(typeof(GrtValue));
        roleEditorBE.add_object(selGrtValue);
      }
      roleObjectListBE.refresh();
      roleObjectListModel.RefreshModel();
    }

    protected override void RefreshFormData() 
    {
      RefreshPrivilegesList();
    }

    #endregion
  }
}


