#include "../lf_mforms.h"

#include "base/string_utilities.h"
#include "../lf_code_editor.h"
#include "tinyxml.h"
#include <memory>
#include <ctype.h>
#include <stdlib.h>
#include "base/wb_memory.h"
#include "base/wb_iterators.h"

#include "Scintilla.h"
#include "SciLexer.h"
#define PLAT_GTK 2
#define GTK
#include "ScintillaWidget.h"

using namespace Scintilla;

static void notify_signal(GtkWidget *w, gint wParam, gpointer lParam, mforms::gtk::CodeEditorImpl *editor)
{
    SCNotification *event = reinterpret_cast<SCNotification *>(lParam);
    editor->notify(event);
}

mforms::gtk::CodeEditorImpl::CodeEditorImpl(CodeEditor* self)
       : ViewImpl(self)
       ,_sci_gtk_widget(0)
       ,_sci_gtkmm_widget(0)
       ,_sci(0)
{
  _sci_gtk_widget = scintilla_new();
  _sci_gtkmm_widget = Glib::wrap(_sci_gtk_widget);
  _sci_gtkmm_widget->reference();
  _sci = SCINTILLA(_sci_gtk_widget);
  _owner = self;
  gtk_signal_connect(GTK_OBJECT(_sci_gtk_widget), SCINTILLA_NOTIFY, GTK_SIGNAL_FUNC(notify_signal), this);
  _sci_gtkmm_widget->show();

  _sci_gtkmm_widget->set_data("mforms", dynamic_cast<mforms::View*>(self));
}

//------------------------------------------------------------------------------
mforms::gtk::CodeEditorImpl::~CodeEditorImpl()
{
  _sci_gtkmm_widget->unreference();
}

//------------------------------------------------------------------------------
Gtk::Widget *mforms::gtk::CodeEditorImpl::get_outer() const
{
  return _sci_gtkmm_widget;
}

//------------------------------------------------------------------------------
bool mforms::gtk::CodeEditorImpl::create(CodeEditor* self)
{
  return new mforms::gtk::CodeEditorImpl(self);
}

//------------------------------------------------------------------------------
void mforms::gtk::CodeEditorImpl::notify(SCNotification *scn)
{
  switch (scn->nmhdr.code)
  {
    case SCN_MARGINCLICK:
      {
         int line = scintilla_send_message(_sci, SCI_LINEFROMPOSITION, scn->position, 0);
         if (scn->margin == 2)
         {
           // Click on the folder margin. Toggle the current line if possible.
           scintilla_send_message(_sci, SCI_TOGGLEFOLD, line, 0);
         }
      }

    default:
      _owner->on_notify(scn);
      break;
  }
}

sptr_t mforms::gtk::CodeEditorImpl::send_editor(CodeEditor* self, unsigned int msg, uptr_t uparam, sptr_t sparam)
{
  CodeEditorImpl* ce = self->get_data<CodeEditorImpl>();
  if (ce) {
    return scintilla_send_message(ce->_sci, msg, uparam, sparam);
  }
  return 0;
}


void mforms::gtk::CodeEditorImpl::set_status_text(CodeEditor *self, const std::string &text)
{
  CodeEditorImpl* ce = self->get_data<CodeEditorImpl>();
  if (ce)
  {
   // no-op for now
   // g_message("set_status_text: %s", text.c_str());
  }
}

//------------------------------------------------------------------------------
void mforms::gtk::CodeEditorImpl::init()
{
  ::mforms::ControlFactory *f = ::mforms::ControlFactory::get_instance();

  f->_code_editor_impl.create = mforms::gtk::CodeEditorImpl::create;
  f->_code_editor_impl.send_editor = mforms::gtk::CodeEditorImpl::send_editor;
  f->_code_editor_impl.set_status_text = mforms::gtk::CodeEditorImpl::set_status_text;
}

