/* 
 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

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

using MySQL.Grt;
using MySQL.Workbench;

namespace MySQL.GUI.Workbench
{
  public class WorkbenchToolbarManager
  {
    #region Member Variables
    
    // The Workbench context.
    // TODO: probably no longer needed, check this.
    //private WbContext wbContext;

    private static WorkbenchToolbarManager instance = null;

    #endregion

    public static WorkbenchToolbarManager Instance
    {
      get
      {
        if (instance == null)
          instance = new WorkbenchToolbarManager(null);
        return instance;
      }
    }

    #region Constructors

    private WorkbenchToolbarManager(WbContext context)
    {
//      wbContext = context;
    }

    #endregion

    #region Toolbar creation

    public delegate bool ToolbarCallback(String command, object data);

    public void UpdateToolbar(ToolStrip toolstrip, List<ToolbarItem> toolbarItems,
          ToolbarCallback callback)
    {
      toolstrip.Tag = callback;
      toolstrip.Items.Clear();
      toolstrip.Items.AddRange(buildToolbar(toolbarItems));
    }

    ToolStripItem[] buildToolbar(List<ToolbarItem> toolbarItems)
    {
      return buildToolbar(toolbarItems, false);
    }

    ToolStripItem[] buildToolbar(List<ToolbarItem> toolbarItems, bool addSpacer)
    {
      ToolStripItem[] itemlist;
      int i = 0;
      GrtIconManager iconManager = GrtIconManager.get_instance();

      if (!addSpacer)
        itemlist = new ToolStripItem[toolbarItems.Count];
      else
        itemlist = new ToolStripItem[toolbarItems.Count + 1];

      // rebuild the menu
      foreach (ToolbarItem subitem in toolbarItems)
      {
        switch (subitem.get_type())
        {
          case ToolbarItemType.ToolbarAction:
            {
              ToolStripButton smitem;

              smitem = new ToolStripButton();
              smitem.Name = subitem.get_name();
              smitem.Tag = subitem.get_command();
              smitem.Image = iconManager.get_icon(subitem.get_icon());
              smitem.ToolTipText = subitem.get_tooltip();
              smitem.ImageScaling = ToolStripItemImageScaling.None;

              smitem.Enabled = subitem.get_enabled();
              smitem.Click += new System.EventHandler(toolbarItem_Click);

              if (smitem.Name.EndsWith("__right"))
                smitem.Alignment = ToolStripItemAlignment.Right;

              itemlist[i++] = smitem;
              break;
            }

          case ToolbarItemType.ToolbarLabel:
            {
              ToolStripLabel smitem;

              smitem = new ToolStripLabel();
              smitem.Name = subitem.get_name();
              smitem.Tag = subitem.get_command();
              smitem.Text = subitem.get_caption();
              smitem.Font = new System.Drawing.Font(smitem.Font.FontFamily, 7);
              smitem.Enabled = subitem.get_enabled();

              if (smitem.Name.EndsWith("__right"))
                smitem.Alignment = ToolStripItemAlignment.Right;

              itemlist[i++] = smitem;
              break;
            }

          case ToolbarItemType.ToolbarSeparator:
            {
              itemlist[i++] = new ToolStripSeparator();
              if (subitem.get_name().EndsWith("__right"))
                itemlist[i - 1].Alignment = ToolStripItemAlignment.Right;
              break;
            }
          case ToolbarItemType.ToolbarRadio:
          case ToolbarItemType.ToolbarToggle:
          case ToolbarItemType.ToolbarCheck:
            {
              ToolStripButton smitem;

              smitem = new ToolStripButton();
              smitem.Name = subitem.get_name();
              smitem.Tag = subitem.get_command();
              if (subitem.get_checked() && subitem.get_alt_icon() != 0)
                smitem.Image = iconManager.get_icon(subitem.get_alt_icon());
              else
                smitem.Image = iconManager.get_icon(subitem.get_icon());
              smitem.ImageScaling = ToolStripItemImageScaling.None;
              smitem.DisplayStyle = ToolStripItemDisplayStyle.Image;
              smitem.ToolTipText = subitem.get_tooltip();
              smitem.Enabled = subitem.get_enabled();
              smitem.Checked = subitem.get_checked();
              smitem.Click += new System.EventHandler(toolbarItem_Click);

              if (smitem.Name.EndsWith("__right"))
                smitem.Alignment = ToolStripItemAlignment.Right;
              if (subitem.get_type() == ToolbarItemType.ToolbarCheck)
                smitem.CheckOnClick = true;

              itemlist[i++] = smitem;
              break;
            }

          case ToolbarItemType.ToolbarDropDown:
            throw new Exception("SQL IDE: Invalid toolbar item used.");

          case ToolbarItemType.ToolbarSearch:
            {
              ToolStripTextBox searchBox = new ToolStripTextBox();
              searchBox.Enabled = true;
              searchBox.AutoSize = false;
              searchBox.Size = new Size(180, 20);
              searchBox.TextBox.MaximumSize = new Size(180, 20);
              searchBox.KeyPress += new KeyPressEventHandler(tb_KeyPress);

              searchBox.Name = subitem.get_name();
              searchBox.Tag = subitem.get_command();
              searchBox.ToolTipText = subitem.get_tooltip();
              if (searchBox.Name.EndsWith("__right"))
                searchBox.Alignment = ToolStripItemAlignment.Right;

              itemlist[i++] = searchBox;
              break;
            }
        }        
      }

      if (addSpacer)
      {
        ToolStripLabel smitem;

        smitem = new ToolStripLabel();
        smitem.Name = "spacerLabel";
        smitem.Tag = null;
        smitem.Text = "        ";
        smitem.Font = new System.Drawing.Font("Tahoma", 8);
        smitem.Enabled = false;

        itemlist[i++] = smitem;
      }

      return itemlist;
    }

    #endregion

    #region Event handling

    void tb_KeyPress(object sender, KeyPressEventArgs e)
    {
      ToolStripTextBox item = sender as ToolStripTextBox;

      if (item.Owner.Tag != null)
      {
        ToolbarCallback activate = item.Owner.Tag as ToolbarCallback;
        activate((String)item.Tag, item.Text);
      }
        /*
      else
        // TODO: probably no longer needed, check this.
        if (e.KeyChar == '\r')
        {
          e.Handled = true;
          LastSearchString = item.Text;
          wbContext.activate_command((String)item.Tag);
        }
        */
    }

    void toolbarItem_Click(object sender, EventArgs e)
    {
      ToolStripItem item = sender as ToolStripItem;

      if (item != null)
      {
        if (item.Owner.Tag != null)
        {
          ToolbarCallback activate = item.Owner.Tag as ToolbarCallback;
          activate((String)item.Tag, null);
        }
        // TODO: probably no longer needed, check this.
        //else
          //wbContext.activate_command((String)item.Tag);
      }
    }

    #endregion

    #region Properties

    public string LastSearchString { get; set; }
    
    #endregion
  }
  

  public class SqlIdeMenuManager
  {
    public class MenuContext
    {
      public MySQL.Grt.ActionList ActionList;

      public delegate List<NodeId> GetSelectedNodes_Delegate();
      public GetSelectedNodes_Delegate GetSelectedNodes;
      public List<NodeId> nodes;
      public delegate List<MySQL.Grt.MenuItem> GetNodesMenuItems_Delegate(List<NodeId> nodes);
      public GetNodesMenuItems_Delegate GetNodesMenuItems;
      public delegate bool TriggerNodesAction_Delegate(String action, List<NodeId> nodes);
      public TriggerNodesAction_Delegate TriggerNodesAction;

      public delegate List<int> GetSelectedRowsCol_Delegate(ref int column);
      public GetSelectedRowsCol_Delegate GetSelectedRowsCol;
      public List<int> rows;
      public int column;
      public delegate List<MySQL.Grt.MenuItem> GetRowsColMenuItems_Delegate(List<int> rows, int column);
      public GetRowsColMenuItems_Delegate GetRowsColMenuItems;
      public delegate bool TriggerRowsColAction_Delegate(String action, List<int> rows, int column);
      public TriggerRowsColAction_Delegate TriggerRowsColAction;
    }

    static public void InitMenu(ContextMenuStrip menu, MenuContext menuContext)
    {
      MenuContext prevMenuContext = menu.Tag as MenuContext;
      if (null == prevMenuContext)
        menu.Opening += OnMenuOpening;
      menu.Tag = menuContext;
    }

    static private void OnMenuOpening(object sender, CancelEventArgs e)
    {
      ContextMenuStrip menu = sender as ContextMenuStrip;
      MenuContext menuContext = menu.Tag as MenuContext;
      List<MySQL.Grt.MenuItem> itemsBE = null;
      menuContext.nodes = null;
      menuContext.rows = null;
      menuContext.column = -1;
      if (null != menuContext.GetSelectedNodes)
      {
        menuContext.nodes = menuContext.GetSelectedNodes();
        if (null == menuContext.nodes)
          menuContext.nodes = new List<NodeId>();
        itemsBE = menuContext.GetNodesMenuItems(menuContext.nodes);
      }
      else if (null != menuContext.GetSelectedRowsCol)
      {
        menuContext.rows = menuContext.GetSelectedRowsCol(ref menuContext.column);
        if (null == menuContext.rows)
          menuContext.rows = new List<int>();
        itemsBE = menuContext.GetRowsColMenuItems(menuContext.rows, menuContext.column);
      }
      menu.Items.Clear();
      if (null == itemsBE)
      {
        e.Cancel = true;
      }
      else
      {
        FillMenuItems(itemsBE, menu.Items);
        e.Cancel = false;
      }
    }

    static private void FillMenuItems(List<MySQL.Grt.MenuItem> itemsBE, ToolStripItemCollection itemsFE)
    {
      foreach (MySQL.Grt.MenuItem itemBE in itemsBE)
      {
        switch (itemBE.get_type())
        {
          case MySQL.Grt.MenuItemType.MenuSeparator:
            {
              itemsFE.Add(new ToolStripSeparator());
            }
            break;
          default:
            {
              ToolStripMenuItem itemFE = new ToolStripMenuItem();
              itemFE.Tag = itemBE.get_name();
              itemFE.Text = itemBE.get_caption();
              itemFE.Enabled = itemBE.get_enabled();
              if (MySQL.Grt.MenuItemType.MenuCascade == itemBE.get_type())
              {
                FillMenuItems(itemBE.get_subitems(), itemFE.DropDownItems);
              }
              else
              {
                itemFE.Click += new EventHandler(OnMenuItemClick);
              }
              itemsFE.Add(itemFE);
            }
            break;
        }
      }
    }

    static private void OnMenuItemClick(object sender, EventArgs e)
    {
      ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
      MenuContext menuContext = GetMenuContext(menuItem.Owner);
      if (null == menuContext)
        return;
      string action = menuItem.Tag as string;
      bool res = false;
      if (null != menuContext.nodes)
      {
        if (!res && (null != menuContext.ActionList))
          res = menuContext.ActionList.trigger_action(action, menuContext.nodes);
        if (!res && (null != menuContext.TriggerNodesAction) && (null != menuContext.nodes))
          res = menuContext.TriggerNodesAction(action, menuContext.nodes);
      }
      else if (null != menuContext.rows)
      {
        if (!res && (null != menuContext.ActionList))
          res = menuContext.ActionList.trigger_action(action, menuContext.rows, menuContext.column);
        if (!res && (null != menuContext.TriggerRowsColAction))
          res = menuContext.TriggerRowsColAction(action, menuContext.rows, menuContext.column);
      }
    }

    static private MenuContext GetMenuContext(ToolStrip toolStrip)
    {
      if (null == toolStrip)
        return null;
      MenuContext menuContext = toolStrip.Tag as MenuContext;
      if (null == menuContext)
      {
        ToolStripDropDownMenu dropDownMenu = toolStrip as ToolStripDropDownMenu;
        if (null == dropDownMenu)
          return null;
        ToolStripItem ownerItem = dropDownMenu.OwnerItem;
        return GetMenuContext(ownerItem.Owner);
      }
      else
        return menuContext;
    }
  }
}
