#ifndef __BASE_EDITOR_H_
#define __BASE_EDITOR_H_

#include "grt/editor_base.h"
#include "sql_editor_wr.h"
#include "GrtTemplates.h"
#include "SigCSlot.h"
#include "UIForm.h"
#include "GrtManager.h"

#ifdef _MSC_VER
using namespace MySQL::Grt;
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Collections::Generic;
#endif

#pragma make_public(::bec::BaseEditor)

namespace MySQL {
namespace Grt {


public ref class BaseEditor : public UIForm
{
public:
  delegate void VoidBaseEditorDelegate(BaseEditor ^value);

protected:

  typedef void (*BaseEditor::VOID_BASE_EDITOR_HANDLER_CB)(::bec::BaseEditor *editor);

  BaseEditor(::bec::BaseEditor *inn)
    : UIForm(inn)
  {}

  DelegateSlot0<void,void> ^refresh_ui_handler;
  VoidBaseEditorDelegate^ add_unlocked_handler_delegate;

private:
  delegate void VoidBaseEditorWrapperDelegate(::bec::BaseEditor *editor);

  VoidBaseEditorWrapperDelegate^ add_unlocked_handler_wrapper_delegate;

  void add_unlocked_handler_wrapper(::bec::BaseEditor *editor)
  { add_unlocked_handler_delegate(gcnew BaseEditor(editor)); }

public:
  void disable_auto_refresh() { ((::bec::BaseEditor*)inner)->block_auto_refresh(); }
  void enable_auto_refresh()  { ((::bec::BaseEditor*)inner)->unblock_auto_refresh(); }

  ::bec::BaseEditor *get_unmanaged_object()
  { return static_cast<::bec::BaseEditor *>(inner); }

  //virtual GrtObject get_object()= 0;
  GrtValue^ get_object() 
  { return gcnew GrtValue(get_unmanaged_object()->get_object()); }

  void add_refresh_ui_handler(DelegateSlot0<void,void>::ManagedDelegate^ slot)
  {
    refresh_ui_handler= gcnew DelegateSlot0<void,void>(slot);
    get_unmanaged_object()->set_refresh_ui_slot(refresh_ui_handler->get_slot());
  }

  void add_unlocked_handler(VoidBaseEditorDelegate^ slot)
  {
    add_unlocked_handler_delegate= slot;
    add_unlocked_handler_wrapper_delegate = 
      gcnew VoidBaseEditorWrapperDelegate(this, &BaseEditor::add_unlocked_handler_wrapper);
    IntPtr ip = Marshal::GetFunctionPointerForDelegate(add_unlocked_handler_wrapper_delegate);
    VOID_BASE_EDITOR_HANDLER_CB cb = static_cast<VOID_BASE_EDITOR_HANDLER_CB>(ip.ToPointer());
    get_unmanaged_object()->add_unlocked_handler(sigc::ptr_fun(cb));
  }

  GRT^ get_grt() { return gcnew GRT(get_unmanaged_object()->get_grt()); }

  GrtManager^ get_grt_manager() { return gcnew GrtManager(get_unmanaged_object()->get_grt_manager()); }

  // lock when frontend starts using the editor, unlock when done
  void lock()
  { get_unmanaged_object()->lock(); }
  
  void unlock()
  { get_unmanaged_object()->unlock(); }


  // for use by subclasses
  void show_exception(String ^title, String ^detail)
  {
    MessageBox::Show(String::Format("An error has occurred while performing the requested action:\n{0}", detail),
      title, MessageBoxButtons::OK, MessageBoxIcon::Error);
  }

  Db::Sql::Sql_editor ^ get_sql_editor() { return gcnew Db::Sql::Sql_editor(get_unmanaged_object()->get_sql_editor()); }

  void show_validation_error(String ^title, String ^reason)
  {
    MessageBox::Show(String::Format("Cannot change property:\n{0}", reason), 
      title, MessageBoxButtons::OK, MessageBoxIcon::Error);
  }

  bool should_close_on_delete_of(String ^oid)
  {
    return get_unmanaged_object()->should_close_on_delete_of(NativeToCppString(oid));
  }

};


} // namespace Grt
} // namespace MySQL

#endif // __BASE_EDITOR_H_
