/* 
 * Copyright (c) 2011, 2013, 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
 */

#include "stdafx.h"

#include "mforms/mforms.h"
#include "wf_view.h"
#include "wf_menubar.h"

#include "ConvUtils.h"

using namespace System::Windows::Forms;
using namespace System::Drawing;

using namespace MySQL::Forms;
using namespace MySQL::Utilities;
using namespace MySQL::Controls;

//----------------- MenuItemImpl -------------------------------------------------------------------

MenuItemImpl::MenuItemImpl(mforms::MenuItem* item)
  : ObjectImpl(item)
{

}

//--------------------------------------------------------------------------------------------------

void MenuItemImpl::menuItemClick(Object^ sender, System::EventArgs^ e)
{
  ToolStripMenuItem^ native_item= (ToolStripMenuItem^) sender;

  if (native_item->Tag != nullptr)
  {
    mforms::MenuItem* item = ViewImpl::get_backend_control<mforms::MenuItem>(native_item);
    if (item != NULL)
      item->callback();
  }
}

//----------------- MenuBarImpl --------------------------------------------------------------------

MenuBarImpl::MenuBarImpl(mforms::MenuBase *self)
  : ObjectImpl(self)
{

}

//--------------------------------------------------------------------------------------------------

MenuBarImpl::~MenuBarImpl()
{

}

//--------------------------------------------------------------------------------------------------

bool MenuBarImpl::create_menu_bar(mforms::MenuBar* item)
{
  MenuBarImpl^ menu = gcnew MenuBarImpl(item);

  if (menu != nullptr)
  {
    MenuStrip^ native_menu = ViewImpl::create<MenuStrip>(item, menu);

    native_menu->AllowDrop = false;
    native_menu->AllowItemReorder = false;
    native_menu->AllowMerge = false;
    native_menu->AutoSize = true;
    native_menu->CanOverflow = false;
    native_menu->Dock = DockStyle::Top;
    native_menu->DefaultDropDownDirection = ToolStripDropDownDirection::BelowRight;
    native_menu->LayoutStyle = ToolStripLayoutStyle::HorizontalStackWithOverflow;
    native_menu->Name = "MenuStrip";
    native_menu->Padding = Padding(0, 2, 0, 2);
    native_menu->RenderMode = ToolStripRenderMode::System;
    native_menu->ShowItemToolTips = false;
    native_menu->Stretch = true;
    native_menu->TabIndex = 0;
    native_menu->TabStop = false;

    switch (base::Color::get_active_scheme())
    {
    case base::ColorSchemeCustom:
    case base::ColorSchemeStandard:
    case base::ColorSchemeStandardWin7:
      {
        TransparentMenuStripRenderer ^renderer = gcnew TransparentMenuStripRenderer();
        native_menu->Renderer = renderer;
      }
    default:
      {
        Win8MenuStripRenderer ^renderer = gcnew Win8MenuStripRenderer();
        native_menu->Renderer = renderer;
      }
    }
    native_menu->Font = native_menu->DefaultFont;

    return true;
  }

  return false;
}

//--------------------------------------------------------------------------------------------------

bool MenuBarImpl::create_context_menu(mforms::ContextMenu* item)
{
  MenuBarImpl^ menu = gcnew MenuBarImpl(item);

  if (menu != nullptr)
  {
    ContextMenuStrip^ native_menu = ViewImpl::create<ContextMenuStrip>(item, menu);

    native_menu->AllowDrop = false;
    native_menu->AllowItemReorder = false;
    native_menu->AllowMerge = false;
    native_menu->AutoSize = true;
    native_menu->CanOverflow = false;
    native_menu->Dock = DockStyle::Top;
    native_menu->DefaultDropDownDirection = ToolStripDropDownDirection::Right;
    native_menu->LayoutStyle = ToolStripLayoutStyle::HorizontalStackWithOverflow;
    native_menu->Name = "MenuStrip";
    native_menu->Padding = Padding(0, 2, 0, 2);
    native_menu->RenderMode = ToolStripRenderMode::System;
    native_menu->ShowItemToolTips = false;
    native_menu->Stretch = true;
    native_menu->TabIndex = 0;
    native_menu->TabStop = false;

    switch (base::Color::get_active_scheme())
    {
    case base::ColorSchemeCustom:
    case base::ColorSchemeStandard:
    case base::ColorSchemeStandardWin7:
      {
        TransparentMenuStripRenderer ^renderer = gcnew TransparentMenuStripRenderer();
        native_menu->Renderer = renderer;
      }
    default:
      {
        Win8MenuStripRenderer ^renderer = gcnew Win8MenuStripRenderer();
        native_menu->Renderer = renderer;
      }
    }
    native_menu->Font = native_menu->DefaultFont;
    native_menu->Opening += gcnew System::ComponentModel::CancelEventHandler(&MenuBarImpl::ContextMenuOpening);

    return true;
  }

  return false;
}

//--------------------------------------------------------------------------------------------------

bool MenuBarImpl::create_menu_item(mforms::MenuItem* item, const std::string& title,
  const mforms::MenuItemType type)
{
  MenuItemImpl^ menu_item = gcnew MenuItemImpl(item);
  if (menu_item != nullptr)
  {
    switch (type)
    {
      case mforms::CheckedMenuItem:
        {
          ToolStripMenuItem^ native_item = ViewImpl::create<ToolStripMenuItem>(item, menu_item, native_item);
          native_item->Text = CppStringToNative(title);
          native_item->Click += gcnew System::EventHandler(menu_item, &MenuItemImpl::menuItemClick); 

          //native_item->CheckOnClick = true; Not supported on the other platforms.
        }
        break;

      case mforms::SeparatorMenuItem:
        {
          ToolStripItem^ native_item = ViewImpl::create<ToolStripSeparator>(item, menu_item, native_item);
          native_item->AutoSize = false;
          native_item->Height = 3;
          native_item->Margin = Padding(32, 0, 2, 0);
        }
        break;

      default:
        {
          ToolStripMenuItem^ native_item = ViewImpl::create<ToolStripMenuItem>(item, menu_item, native_item);
          native_item->Text = CppStringToNative(title);
          native_item->Click += gcnew System::EventHandler(menu_item, &MenuItemImpl::menuItemClick); 
        }
        break;
    }

    return true;
  }

  return false;
}

//--------------------------------------------------------------------------------------------------

void MenuBarImpl::set_title(mforms::MenuItem* item, const std::string& title)
{
  MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  if (menu_item != nullptr)
    menu_item->get_control<ToolStripItem>()->Text = CppStringToNative(title);
}

//--------------------------------------------------------------------------------------------------

std::string MenuBarImpl::get_title(mforms::MenuItem* item)
{
  MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  if (menu_item != nullptr)
    return NativeToCppString(menu_item->get_control<ToolStripItem>()->Text);

  return "";
}

//--------------------------------------------------------------------------------------------------

void MenuBarImpl::set_shortcut(mforms::MenuItem* item, const std::string& value)
{
  MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  if (menu_item != nullptr)
    menu_item->get_control<ToolStripMenuItem>()->ShortcutKeys = MenuManager::convertShortcut(CppStringToNative(value));
}

//--------------------------------------------------------------------------------------------------

void MenuBarImpl::set_enabled(mforms::MenuBase* item, bool state)
{
  MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  if (menu_item != nullptr)
    menu_item->get_control<ToolStripItem>()->Enabled = state;
}

//--------------------------------------------------------------------------------------------------

bool MenuBarImpl::get_enabled(mforms::MenuBase* item)
{
  MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  if (menu_item != nullptr)
    return menu_item->get_control<ToolStripItem>()->Enabled;

  return false;
}

//--------------------------------------------------------------------------------------------------

void MenuBarImpl::set_checked(mforms::MenuItem* item, bool state)
{
  MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  if (menu_item != nullptr)
    menu_item->get_control<ToolStripMenuItem>()->Checked = state;
}

//--------------------------------------------------------------------------------------------------

bool MenuBarImpl::get_checked(mforms::MenuItem* item)
{
  MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  if (menu_item != nullptr)
    return menu_item->get_control<ToolStripMenuItem>()->Checked;

  return false;
}

//--------------------------------------------------------------------------------------------------

void MenuBarImpl::insert_item(mforms::MenuBase *menu, int index, mforms::MenuItem *item)
{
  MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  
  if (dynamic_cast<mforms::MenuBar*>(menu) != NULL || dynamic_cast<mforms::ContextMenu*>(menu) != NULL)
  {
    MenuBarImpl^ native_menubar = (MenuBarImpl^) ViewImpl::FromUnmanaged(menu);
    MenuItemImpl^ menu_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
    if (native_menubar != nullptr && menu_item != nullptr)
    {
      ToolStrip^ native_menu = native_menubar->get_control<ToolStrip>();
      ToolStripItem^ native_item = menu_item->get_control<ToolStripItem>();

      if (native_menu->Items->Count == index)
        native_menu->Items->Add(native_item);
      else
        native_menu->Items->Insert(index, native_item);
    }
  }
  else
  {
    // This passed in new owner is actually another menu item.
    MenuItemImpl^ parent_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(menu);
    if (parent_item != nullptr && menu_item != nullptr)
    {
      ToolStripMenuItem^ native_parent = parent_item->get_control<ToolStripMenuItem>();
      ToolStripItem^ native_item = menu_item->get_control<ToolStripItem>();

      if (native_parent->DropDownItems->Count == index)
        native_parent->DropDownItems->Add(native_item);
      else
        native_parent->DropDownItems->Insert(index, native_item);

      // Register drop down delegate if this is the first item that was added.
      if (native_parent->DropDownItems->Count == 1)
        native_parent->DropDownOpening += gcnew System::EventHandler(&MenuBarImpl::DropDownOpened);
    }
  }
}

//--------------------------------------------------------------------------------------------------

void MenuBarImpl::remove_item(mforms::MenuBase *menu, mforms::MenuItem *item)
{
  MenuItemImpl^ menu_item = item == NULL ? nullptr : (MenuItemImpl^) ViewImpl::FromUnmanaged(item);
  if (dynamic_cast<mforms::MenuBar*>(menu) != NULL || dynamic_cast<mforms::ContextMenu*>(menu) != NULL)
  {
    // This is the top menu bar or context menu.
    MenuBarImpl^ menu_bar = (MenuBarImpl^) ViewImpl::FromUnmanaged(menu);
    if (menu_bar != nullptr)
    {
      ToolStrip^ native_menu = menu_bar->get_control<ToolStrip>();

      if (menu_item != nullptr)
      {
        ToolStripMenuItem^ native_item = menu_item->get_control<ToolStripMenuItem>();
        native_menu->Items->Remove(native_item);
      }
      else
        native_menu->Items->Clear();
    }
  }
  else
  {
    // A menu item with drop down items.
    MenuItemImpl^ parent_item = (MenuItemImpl^) ViewImpl::FromUnmanaged(menu);
    if (parent_item != nullptr)
    {
      ToolStripMenuItem^ native_menu = parent_item->get_control<ToolStripMenuItem>();

      if (menu_item != nullptr)
      {
        ToolStripMenuItem^ native_item = menu_item->get_control<ToolStripMenuItem>();
        native_menu->DropDownItems->Remove(native_item);
      }
      else
        native_menu->DropDownItems->Clear();

      // Remove drop down delegate if there are no drop down items anymore.
      if (native_menu->DropDownItems->Count == 0)
        native_menu->DropDownOpening -= gcnew System::EventHandler(&MenuBarImpl::DropDownOpened);
    }
  }
}

//--------------------------------------------------------------------------------------------------

void MenuBarImpl::DropDownOpened(Object^ sender, System::EventArgs^ e)
{
  ToolStripMenuItem^ native_item= dynamic_cast<ToolStripMenuItem^>(sender);
  if (native_item != nullptr)
  {
    mforms::MenuItem* item = ObjectImpl::get_backend_control<mforms::MenuItem>(native_item);
    if (item != NULL)
    {
      mforms::MenuBase* menu = item->get_top_menu();
      if (dynamic_cast<mforms::MenuBar*>(menu) != NULL)
        dynamic_cast<mforms::MenuBar*>(menu)->will_show_submenu_from(item);
      else if (dynamic_cast<mforms::ContextMenu*>(menu) != NULL)
        dynamic_cast<mforms::ContextMenu*>(menu)->will_show_submenu_from(item);
    }
  }
}

//--------------------------------------------------------------------------------------------------

void MenuBarImpl::ContextMenuOpening(Object^ sender, System::ComponentModel::CancelEventArgs^ e)
{
  ContextMenuStrip^ native_menu= dynamic_cast<ContextMenuStrip^>(sender);
  if (native_menu != nullptr)
  {
    mforms::ContextMenu* menu = ObjectImpl::get_backend_control<mforms::ContextMenu>(native_menu);
    if (menu != NULL)
    {
      menu->will_show();
    }
  }
}

//--------------------------------------------------------------------------------------------------

ToolStrip^ MenuBarImpl::GetNativeControl(mforms::MenuBase *menu)
{
  MenuBarImpl^ wrapper = (MenuBarImpl^) ObjectImpl::FromUnmanaged(menu);
  return wrapper->get_control<ToolStrip>();
}

//--------------------------------------------------------------------------------------------------

