/* 
 * © 2007-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include "stdafx.h"

#include "grtdb_connection_editor.h"

#include "cppdbc.h"
#include "grtpp_util.h"
#include <grt/common.h>

//------------------------------------------------------------------------------
grtui::DbConnectionEditor::DbConnectionEditor(const db_mgmt_ManagementRef &mgmt)
  : mforms::Form(0)
  , _mgmt(mgmt)
  , _panel(false)
  , _top_vbox(false)
  , _top_hbox(true)
  , _conn_list_buttons_hbox(true)
  , _stored_connection_list(::mforms::TreeShowHeader)
  , _bottom_hbox(true)
{
  set_title(_("Manage DB Connections"));
  
  _top_vbox.set_padding(MF_WINDOW_PADDING);
  _top_vbox.set_spacing(12);
  _top_hbox.set_spacing(8);
  _top_vbox.add(&_top_hbox, true, true);
  _top_vbox.add(&_bottom_hbox, false, true);
  
  _bottom_hbox.set_spacing(12);
  
  _panel.init(_mgmt);
  
  _stored_connection_list.signal_changed().connect(sigc::mem_fun(this, &grtui::DbConnectionEditor::change_active_stored_conn));

  _conn_name= _panel.get_name_entry();
  _conn_name->signal_changed().connect(sigc::mem_fun(this, &grtui::DbConnectionEditor::name_changed));

  
  _del_conn_button.set_text(_("Delete"));
  _del_conn_button.signal_clicked().connect(sigc::mem_fun(this, &grtui::DbConnectionEditor::del_stored_conn));
  _add_conn_button.set_text(_("New"));
  _add_conn_button.signal_clicked().connect(sigc::mem_fun(this, &grtui::DbConnectionEditor::add_stored_conn));

  _top_hbox.add(&_stored_connection_list, false, true);  
  _top_hbox.add(&_panel, true, true);

  _bottom_hbox.add(&_add_conn_button, false, true);
  _bottom_hbox.add(&_del_conn_button, false, true);
  _bottom_hbox.add(&_test_button, false, true);
  
  _bottom_hbox.add_end(&_ok_button, false, true);
//  _bottom_hbox.add_end(&_cancel_button, false, true);
  
  _ok_button.set_text(_("Close"));
  _ok_button.signal_clicked().connect(sigc::mem_fun(this, &DbConnectionEditor::ok_clicked));
//  _cancel_button.set_text(_("Cancel"));
//  _cancel_button.signal_clicked().connect(sigc::mem_fun(this, &DbConnectionEditor::cancel_clicked));
  _test_button.set_text(_("Test Connection"));
  _test_button.signal_clicked().connect(sigc::mem_fun(this, &DbConnectionEditor::test_clicked));

  _add_conn_button.enable_internal_padding(true);
  _del_conn_button.enable_internal_padding(true);
  _ok_button.enable_internal_padding(true);
  _cancel_button.enable_internal_padding(true);  
  _test_button.enable_internal_padding(true);
  
  _stored_connection_list.set_size(180, -1);
  
  set_content(&_top_vbox);
  

  _stored_connection_list.add_column(::mforms::StringColumnType, _("Stored Connections"), 150, false);
  _stored_connection_list.end_columns();
  
  set_size(800, 500);
}

//------------------------------------------------------------------------------
grtui::DbConnectionEditor::~DbConnectionEditor()
{
}

//------------------------------------------------------------------------------
db_mgmt_ConnectionRef grtui::DbConnectionEditor::run(const db_mgmt_ConnectionRef &connection)
{
  reset_stored_conn_list();
  
  // set the displayed params to the one given to us
  _panel.get_be()->set_connection(connection);
  // switch the connection object with the anon connection from the panel object
  _panel.get_be()->set_connection_keeping_parameters(_panel.get_default_connection());

  _conn_name->set_value(_("Press New to save these settings"));

  // return the selected connection object
  if (run_modal(&_ok_button, &_cancel_button))
    return _panel.get_be()->get_connection();

  return db_mgmt_ConnectionRef();
}


//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::run()
{
  reset_stored_conn_list();
    
  run_modal(&_ok_button, &_cancel_button);
}

//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::reset_stored_conn_list()
{
  grt::ListRef<db_mgmt_Connection> list(_panel.get_be()->get_db_mgmt()->storedConns());
  std::string selected_name;
  
  if (_panel.get_be()->get_connection().is_valid())
    selected_name= _panel.get_be()->get_connection()->name();
  
  _stored_connection_list.clear_rows();

  int selected_idx= -1;
  int added_row_idx = -1;
  grt::ListRef<db_mgmt_Connection>::const_iterator iter = list.begin();
  grt::ListRef<db_mgmt_Connection>::const_iterator last = list.end();
  for (; iter != last; ++iter)
  {
    added_row_idx = _stored_connection_list.add_row();
    if (added_row_idx >= 0)
    {
      _stored_connection_list.set(added_row_idx, 0, (*iter)->name());
      if ((*iter)->name() == selected_name)
        selected_idx= added_row_idx;
    }
  }

  if (selected_idx > 0)
  {
    selected_idx = selected_idx >= 0 ? selected_idx : 0;
    _stored_connection_list.set_selected(selected_idx);
  }
  change_active_stored_conn();
}

//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::add_stored_conn()
{
  grt::ListRef<db_mgmt_Connection> list(_panel.get_be()->get_db_mgmt()->storedConns());
  const int length = (std::string("New connection 1")).length() - 1;
  int max_conn_nr = 0;
  for (size_t i = 0; i < list.count(); ++i)
  {
    std::string itname = list[i]->name();
    if (itname.find("New connection") == 0)
    {
      int conn_nr = atoi(itname.substr(length).c_str());
      if (conn_nr > max_conn_nr)
        max_conn_nr = conn_nr;
    }
  }
  char buf[128];
  sprintf(buf, "New connection %i", max_conn_nr + 1);

  // use the current values to create a new connection
  db_mgmt_ConnectionRef new_connection(_panel.get_be()->get_grt());
  
  new_connection->owner(_panel.get_be()->get_db_mgmt());
  new_connection->name(buf);
  list.insert(new_connection);
  
  _panel.get_be()->set_connection_keeping_parameters(new_connection);

  reset_stored_conn_list();
  change_active_stored_conn();
}

//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::del_stored_conn()
{
  const int idx = _stored_connection_list.get_selected();
  if (idx >= 0)
  {
    grt::ListRef<db_mgmt_Connection> conns= _mgmt->storedConns();
    if (idx < (int)conns.count())
      conns.remove(idx);
    
    reset_stored_conn_list();
    change_active_stored_conn();
  }
}

//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::change_active_stored_conn()
{
  const int selected = _stored_connection_list.get_selected();
  if (selected >= 0)
  {
    _panel.set_enabled(true);    
    _panel.set_active_stored_conn(selected+1);
  }
  else
    _panel.set_enabled(false);
}

//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::name_changed()
{
  std::string name= _conn_name->get_string_value();
  
  std::string oname= _stored_connection_list.get_string(_stored_connection_list.get_selected(), 0);
  
  if (rename_stored_conn(oname, name))
    _stored_connection_list.set(_stored_connection_list.get_selected(), 0, name);
}

//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::ok_clicked()
{
  // dont need to do anything, the modal handler will interpret the close butto
}

//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::cancel_clicked()
{
}

//------------------------------------------------------------------------------
void grtui::DbConnectionEditor::test_clicked()
{
  try
  {
    sql::DriverManager *dbc_drv_man= sql::DriverManager::getDriverManager();
    std::auto_ptr<sql::Connection> _dbc_conn= dbc_drv_man->getConnection(_panel.get_be()->get_connection());
  
    if (_dbc_conn.get() && !_dbc_conn->isClosed())
      mforms::Utilities::show_message("Connect", "Connect parameters are correct", "Ok");
    else
      mforms::Utilities::show_error("Connect", "Connect failed", "Ok");
  }
  catch (const std::exception& e)
  {
    mforms::Utilities::show_error("Test connect failed", e.what(), "Ok");
  }
}

//------------------------------------------------------------------------------
bool grtui::DbConnectionEditor::rename_stored_conn(const std::string &oname, const std::string &name)
{
  if (name == oname) return true;
  
  grt::ListRef<db_mgmt_Connection> conns= _mgmt->storedConns();
  db_mgmt_ConnectionRef conn= find_named_object_in_list(conns, oname);
  
  if (conn.is_valid())
  {
    // check for duplicate
    if (find_named_object_in_list(conns, name).is_valid())
      return false;
    
    conn->name(name);
    return true;
  }
  return false;
}


