#ifndef __UIFORM_H__
#define __UIFORM_H__

#include "grt/ui_form.h"
#include "SigCSlot.h"

#pragma make_public(::bec::UIForm)
#pragma make_public(::bec::MenuItem)

namespace MySQL {
  namespace Grt {

    public enum class MenuItemType
    {
      MenuAction=        ::bec::MenuAction,
      MenuSeparator=     ::bec::MenuSeparator,
      MenuCascade=       ::bec::MenuCascade,
      MenuCheck=         ::bec::MenuCheck,
      MenuRadio=         ::bec::MenuRadio,

      MenuUnavailable=   ::bec::MenuUnavailable
    };

    
    public ref class MenuItem
    {
      String^ caption;
      String^ shortcut;
      String^ name;
      MenuItemType type;

      bool enabled;
      bool checked;

    public:

      MenuItem(const ::bec::MenuItem& item)
        : caption(CppStringToNative(item.caption)),
        shortcut(CppStringToNative(item.shortcut)),
        name(CppStringToNative(item.name)),
        type((MenuItemType)item.type),
        enabled(item.enabled),
        checked(item.checked)
      {}

      String^ get_caption()
      { return caption; }

      String^ get_shortcut()
      { return shortcut; }

      String^ get_name()
      { return name; }

      MenuItemType get_type()
      { return type; }

      bool get_checked()
      { return checked; }

      bool get_enabled()
      { return enabled; }
    };



    public ref class UIForm
    {
    protected:
      ::bec::UIForm *inner;
      GCHandle m_gch;

      UIForm(::bec::UIForm *inn)
        : inner(inn)
      {
        // get a fixed pointer to this object
        IntPtr ip = this->GetFixedId();

        // set it as the user data
        inner->set_frontend_data((void*)(intptr_t)ip);

        backend_destroyed_cb(gcnew BackendDestroyedDelegate::ManagedDelegate(this, &UIForm::on_backend_destroyed));
      }

      // Returns a fixed pointer to this object that will not be modified by the GC
      IntPtr GetFixedId()
      {
        if (!m_gch.IsAllocated)
           m_gch = GCHandle::Alloc( this );
         return GCHandle::ToIntPtr( m_gch );
      }

      // Needs to be called when destroying the object
      void ReleaseHandle()
      {
        m_gch.Free();
      }

    public:
      virtual ~UIForm()
      { 
        ReleaseHandle();
        delete inner; 
      }

      ::bec::UIForm *get_unmanaged_object()
      { return inner; }

        // Returns the object based on the fixed pointer retrieved by GetFixedId()
      static UIForm^ GetFromFixedId( IntPtr ip )
      {
        GCHandle gcHandle = GCHandle::FromIntPtr( ip );
        return (UIForm^)gcHandle.Target;
      }

    public:
      typedef DelegateSlot0<void, void> BackendDestroyedDelegate;
      void backend_destroyed_cb(BackendDestroyedDelegate::ManagedDelegate ^cb)
      {
        on_backend_destroyed_delegate= gcnew BackendDestroyedDelegate(cb);
        inner->slot_destroyed= on_backend_destroyed_delegate->get_slot();
      }
    protected:
      BackendDestroyedDelegate^ on_backend_destroyed_delegate;
      void on_backend_destroyed()
      {
        inner= NULL;
      }
    };

  } // namespace Grt
} // namespace MySQL

#endif // __UIFORM_H__