#ifndef __OVERVIEW_H__
#define __OVERVIEW_H__

#include "workbench/wb_overview.h"
#include "GrtTemplates.h"

#ifdef _MSC_VER
#include  <vcclr.h> // .net interop helpers
using namespace MySQL::Grt;
using namespace System;
using namespace System::Collections::Generic;
#endif


namespace MySQL {
  namespace Workbench {

    public ref class Overview : public ::MySQL::Grt::TreeModel
    {
    protected:
      ref class OverviewUIForm : public ::MySQL::Grt::UIForm
      {
      public:
        OverviewUIForm(::bec::UIForm *inn)
          : UIForm(inn)
        {}

        virtual ~OverviewUIForm()
        {
          inner = nullptr;
        }
      };

      OverviewUIForm^ uiform;

    public:
      enum class Columns
      {
        Label= ::wb::OverviewBE::Label,
        NodeType = ::wb::OverviewBE::NodeType,
        ChildNodeType = ::wb::OverviewBE::ChildNodeType,
        Expanded = ::wb::OverviewBE::Expanded,
        Height = ::wb::OverviewBE::Height,
        DisplayMode = ::wb::OverviewBE::DisplayMode,

        FirstDetailField = ::wb::OverviewBE::FirstDetailField
      };
      enum class NodeType
      {
        Root= ::wb::OverviewBE::ORoot,
        Division= ::wb::OverviewBE::ODivision,
        Group= ::wb::OverviewBE::OGroup,
        Section= ::wb::OverviewBE::OSection,
        Item= ::wb::OverviewBE::OItem,
        Special= ::wb::OverviewBE::OSpecial
      };
      enum class DisplayMode
      {
        None= ::wb::OverviewBE::MNone,
        LargeIcon= ::wb::OverviewBE::MLargeIcon,
        SmallIcon= ::wb::OverviewBE::MSmallIcon,
        List= ::wb::OverviewBE::MList
      };

      inline ::wb::OverviewBE *get_unmanaged_object()
      { return static_cast<::wb::OverviewBE*>(TreeModel::get_unmanaged_object()); }


      Overview(::wb::OverviewBE *inn)
        : ::MySQL::Grt::TreeModel(inn)
      { 
        uiform = gcnew OverviewUIForm(inn);
      }

      UIForm^ get_uiform()
      {
        return uiform;
      }

      bool matches_handle(IntPtr handle)
      {
        return (dynamic_cast<bec::UIForm*>(get_unmanaged_object()) == reinterpret_cast<bec::UIForm*>(handle.ToPointer()));
      }

      String^ get_title()
      {
        std::string title= get_unmanaged_object()->get_title();
	      if (title.empty()) return nullptr;
	      return CppStringToNative(title);
      }

      //NodeId get_child(const NodeId &parent, int index);
      //int count_children(const NodeId &parent);

      //bool get_field(const NodeId &node, int column, std::string &value);
      //bool get_field(const NodeId &node, int column, int &value);
      //std::string get_field_description(const NodeId &node, int column);
      
      //::MySQL::Grt::IconId get_field_icon(::MySQL::Grt::NodeId^ node, int column)
      //{
      //  return (::MySQL::Grt::IconId)get_unmanaged_object()->get_field_icon(*node->get_unmanaged_object(), column);
      //}

      String^ get_node_unique_id(::MySQL::Grt::NodeId^ node)
      {
	      std::string id= get_unmanaged_object()->get_node_unique_id(*node->get_unmanaged_object());
	      if (id.empty()) return nullptr;
	      return CppStringToNative(id);
      }


      ::MySQL::Grt::NodeId^ get_focused_child(::MySQL::Grt::NodeId^ node)
      {
        return gcnew ::MySQL::Grt::NodeId(&get_unmanaged_object()->get_focused_child(*node->get_unmanaged_object())); 
      }

      void select_node(::MySQL::Grt::NodeId^ node)
      {
        get_unmanaged_object()->select_node(*node->get_unmanaged_object());
      }

      List<int>^ get_selected_children(::MySQL::Grt::NodeId^ node)
      {
        List<int>^ list= gcnew List<int>();

        std::list<int> items= get_unmanaged_object()->get_selected_children(*node->get_unmanaged_object());

        for (std::list<int>::iterator i= items.begin(); i != items.end(); ++i)
          list->Add(*i);

        return list;
      }

      void focus_node(::MySQL::Grt::NodeId^ node)
      {
        get_unmanaged_object()->focus_node(*node->get_unmanaged_object());
      }

      void begin_selection_marking()
      {
        get_unmanaged_object()->begin_selection_marking();
      }

      void end_selection_marking()
      {
        get_unmanaged_object()->end_selection_marking();
      }


      bool is_editable(::MySQL::Grt::NodeId^ node)
      {
        return get_unmanaged_object()->is_editable(*node->get_unmanaged_object());
      }

      bool request_add_object(::MySQL::Grt::NodeId^ node)
      {
        return get_unmanaged_object()->request_add_object(*node->get_unmanaged_object());
      }

      bool request_delete_object(::MySQL::Grt::NodeId^ node)
      {
          return get_unmanaged_object()->request_delete_object(*node->get_unmanaged_object());
      }

      bool request_delete_selection()
      {
        return get_unmanaged_object()->request_delete_selected();
      }

      void refresh_node(::MySQL::Grt::NodeId^ node, bool children)
      {
        try
        {
          get_unmanaged_object()->refresh_node(*node->get_unmanaged_object(), children);
        }
        catch (std::exception &exc)
        {
          OutputDebugStringA(strfmt("Exception during overview refresh: %s\n", exc.what()).c_str());
        }
      }

      String ^get_field_name(::MySQL::Grt::NodeId^ node, int column)
      {
        std::string name= get_unmanaged_object()->get_field_name(*node->get_unmanaged_object(), column);
        return CppStringToNative(name);
      }

      int get_details_field_count(::MySQL::Grt::NodeId^ node)
      {
        return get_unmanaged_object()->get_details_field_count(*node->get_unmanaged_object());
      }

      ::MySQL::Grt::NodeId^ search_child_item_node_matching(::MySQL::Grt::NodeId ^node, 
                                                        ::MySQL::Grt::NodeId^ starting_node,
                                                        String ^text)
      {
        bec::NodeId cnode= node != nullptr ? *node->get_unmanaged_object() : bec::NodeId();
        bec::NodeId cstarting_node= starting_node != nullptr ? *starting_node->get_unmanaged_object() : bec::NodeId();

        bec::NodeId result= get_unmanaged_object()->search_child_item_node_matching(cnode, 
                                                          cstarting_node,
                                                          NativeToCppString(text));

        if (result.is_valid())
          return gcnew ::MySQL::Grt::NodeId(&result);
        return nullptr;
      }
    };

  } // namespace Workbench
} // namespace MySQL

#endif // __OVERVIEW_H__
