#include "mysql_table_editor_fe.h"
#include "linux_utilities/MGGladeXML.h"
#include "grtdb/db_object_helpers.h"
#include "treemodel_wrapper.h"

#include "mysql_table_editor_insert_page.h"
#include <gtkmm/window.h>
#include <gtkmm/textview.h>

//------------------------------------------------------------------------------
DbMySQLTableEditorInsertPage::DbMySQLTableEditorInsertPage(DbMySQLTableEditor *owner
                                                      ,MySQLTableEditorBE *be
                                                      ,MGGladeXML         *xml)
                             : _owner(owner)
                             , _be(be)
                             , _xml(xml)
{
  Gtk::Button *btn(0);
  _xml->get("open_editor_button", &btn);
  btn->signal_clicked().connect(sigc::mem_fun(this, &DbMySQLTableEditorInsertPage::open_editor));

  _xml->get("insert_editor_window", &_editor_window);
  _editor_window->signal_delete_event().connect(sigc::mem_fun(this, &DbMySQLTableEditorInsertPage::window_delete_event));
  _editor_window->set_transient_for(*get_mainwindow());
  _xml->get("inserts_grid", &_inserts_tv);
    
  _inserts_tv->signal_key_press_event().connect_notify(sigc::mem_fun(this, &DbMySQLTableEditorInsertPage::editor_key_pressed));
  
  _xml->get("ok_btn", &btn);
  btn->signal_clicked().connect(sigc::mem_fun(this, &DbMySQLTableEditorInsertPage::ok_click));

  _xml->get("cancel_btn", &btn);
  btn->signal_clicked().connect(sigc::mem_fun(_editor_window, &Gtk::Window::hide));
}

//------------------------------------------------------------------------------
void DbMySQLTableEditorInsertPage::switch_be(MySQLTableEditorBE* be)
{
  _inserts_tv->unset_model();
  _inserts_tv->remove_all_columns();

  _be = be;
}

//------------------------------------------------------------------------------
bool DbMySQLTableEditorInsertPage::window_delete_event(GdkEventAny* event)
{
  _editor_window->hide();
  return true;
}

//------------------------------------------------------------------------------
void DbMySQLTableEditorInsertPage::ok_click()
{
  _be->update_from_inserts_grid();
  _editor_window->hide();
}

//------------------------------------------------------------------------------
void DbMySQLTableEditorInsertPage::refresh()
{
  Gtk::TextView *tv(0);
  _xml->get("inserts_textview", &tv);
  const std::string inserts = _be->get_inserts();
  tv->get_buffer()->set_text(inserts);
  _be->get_inserts_grid()->set_inserts_text(inserts);
}

//------------------------------------------------------------------------------
void DbMySQLTableEditorInsertPage::open_editor()
{
  update_editor();
  _editor_window->show();
}

//------------------------------------------------------------------------------
void DbMySQLTableEditorInsertPage::update_editor()
{
  ::bec::TableInsertsGridBE *grid = _be->get_inserts_grid();
  
  _inserts_tv->unset_model();
  _inserts_tv->remove_all_columns();

  grid->refresh();

  Glib::RefPtr<ListModelWrapper> new_model = ListModelWrapper::create(grid, _inserts_tv, "InsertPage");

  const int n_cols = grid->get_column_count();
  for ( int i = 0; i < n_cols; ++i )
  {
    switch ( grid->get_column_type(i) )
    {
      case ::bec::GridModel::StringType:
      case ::bec::GridModel::DatetimeType:
      case ::bec::GridModel::BlobType: 
      case ::bec::GridModel::NumericType:
      {
        // We need to add 1 to i, as i in the first iteration is equal to 0, so
        // our fake-value getter will not be called
        new_model->model().append_string_column(-(i+1), grid->get_column_caption(i), EDITABLE, NO_ICON);
        break;
      }
      case ::bec::GridModel::UnknownType:
        break;
    }
  }

  new_model->set_fake_column_value_getter(sigc::mem_fun(this, &DbMySQLTableEditorInsertPage::get_cell_value));                                                               
  new_model->set_fake_column_value_setter(sigc::mem_fun(this, &DbMySQLTableEditorInsertPage::set_cell_value));                                                               

  grid->enable_placeholder_row(true);

  _inserts_model = new_model;
  _inserts_tv->set_model(_inserts_model);
}

//------------------------------------------------------------------------------
void DbMySQLTableEditorInsertPage::get_cell_value(const Gtk::TreeModel::iterator& iter, int column, Glib::ValueBase& value)
{
  ::bec::TableInsertsGridBE          *grid = _be->get_inserts_grid();
  const int                            col = -(column + 1); // Shift column value by 1. So we have 0 for -1
							    // As we have here -1 column which is really 
							    // should be 0. That is because get_cell_value
							    // is not called for columns >= 0
  const bec::GridModel::ColumnType    type = grid->get_column_type(col);

  switch ( type )
  {
    case bec::GridModel::StringType: 	
    case bec::GridModel::DatetimeType: 	
    case bec::GridModel::BlobType:
    case bec::GridModel::NumericType:
      {
        bec::NodeId   node(_inserts_model->node_for_iter(iter));
        std::string   val;
        
        grid->get_field(node, col, val);
        set_glib_string(value, val);

        break;
      }
    case bec::GridModel::UnknownType:
    default:
      {
        set_glib_string(value, "<UNKN>");
      }
  }
}

//------------------------------------------------------------------------------
void DbMySQLTableEditorInsertPage::set_cell_value(const Gtk::TreeModel::iterator& iter, int column, const Glib::ValueBase& value)
{
  bec::NodeId   node(_inserts_model->node_for_iter(iter));

  ::bec::TableInsertsGridBE  *grid = _be->get_inserts_grid();

  Glib::Value<std::string>   v;                                                                                                   
  v.init(value.gobj()); 

  // Shift column value by 1. So we have 0 for -1 as we have here -1 column which is really 
  // should be 0. That is because get_cell_value is not called for columns >= 0
  grid->set_convert_field(node, -(column + 1), v.get());
  
  grid->refresh();
  _inserts_tv->unset_model();
  _inserts_tv->set_model(_inserts_model);
}


void DbMySQLTableEditorInsertPage::editor_key_pressed(GdkEventKey *ev)
{
  if (ev->keyval == GDK_Delete)
  {
    Gtk::TreeModel::iterator iter= _inserts_tv->get_selection()->get_selected();
    
    if (iter)
    {
      bec::NodeId node(_inserts_model->node_for_iter(iter));
      ::bec::TableInsertsGridBE  *grid = _be->get_inserts_grid();
      
      grid->delete_node(node);
      _inserts_model->row_deleted(_inserts_model->get_path(iter));
    }
  }
}
