/* 
 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "stdafx.h"

#include "wb_config.h"

#include "grtui/grt_wizard_plugin.h"
#include "grtui/wizard_finished_page.h"
#include "grtui/wizard_view_text_page.h"

#include "grtui/grtdb_object_filter.h"

#include "db_mysql_sql_script_sync.h"
#include "base/string_utilities.h"
#include "mforms/fs_object_selector.h"

using namespace grtui;
using namespace mforms;


#include "synchronize_differences_page.h"


namespace ScriptSynchronize {

  
class WbPluginSQLSynchronize : public WizardPlugin
{
  DbMySQLScriptSync _be;
  
public:
  WbPluginSQLSynchronize(grt::Module *module);

  DbMySQLScriptSync *get_be() { return &_be; }
};

  

class ExportInputPage : public WizardPage
{
public:
  ExportInputPage(WizardPlugin *form)
    : WizardPage(form, "options")//, _options(mforms::TitledBoxPanel)
  {
    set_title(_("Model Synchronize and ALTER Script Options"));
    set_short_title(_("Synchronization Options"));

    _options_box.set_padding(12);
    _options_box.set_row_spacing(8);
    _options_box.set_column_spacing(4);
    
    _options_box.set_column_count(3);
    _options_box.set_row_count(5);

    _options_box.add(&_in_descr, 0, 3, 0, 1, HFillFlag);
    _options_box.add(&_in_label, 0, 1, 1, 2, HFillFlag);
    _options_box.add(&_in_entry, 1, 2, 1, 2, HExpandFlag | HFillFlag);
    _options_box.add(&_in_button, 2, 3, 1, 2, NoFillExpandFlag);
    _in_descr.set_text(_("Pick the SQL script file to be compared with the current model. Script must include schema qualifiers."));
    _in_label.set_text(_("Input File:"));
    
    std::string input= form->module()->document_string_data("input_filename", "");
    _in_selector= mforms::manage(new FsObjectSelector(&_in_button, &_in_entry));
    _in_selector->initialize(input, mforms::OpenFile, "SQL Files (*.sql)|*.sql", _("Browse..."));
    scoped_connect(_in_selector->signal_changed(),boost::bind(&ExportInputPage::validate, this));

    _options_box.add(&_out_descr, 0, 3, 2, 3);
    _options_box.add(&_out_label, 0, 1, 3, 4, mforms::HFillFlag);
    _options_box.add(&_out_entry, 1, 2, 3, 4, HExpandFlag | HFillFlag);
    _options_box.add(&_out_button, 2, 3, 3, 4, NoFillExpandFlag);
    _options_box.add(&_skip_out_label, 1, 2, 4, 5, HFillFlag);
    _skip_out_label.set_text(_("Leave blank to view generated script but not save to a file."));
    _skip_out_label.set_style(SmallHelpTextStyle);
    
    _out_descr.set_text(_("Enter the path for the ALTER script to be created."));
    _out_label.set_text(_("Output File:"));

    std::string output= form->module()->document_string_data("output_filename", "");
    _out_selector= mforms::manage(new FsObjectSelector(&_out_button, &_out_entry));
    _out_selector->initialize(output, mforms::SaveFile, "SQL Files (*.sql)|*.sql", _("Browse..."));
    scoped_connect(_out_selector->signal_changed(),boost::bind(&ExportInputPage::validate, this));

    add(&_options_box, false, false);

    scoped_connect(signal_leave(),boost::bind(&ExportInputPage::gather_options, this, _1));
  }


  void gather_options(bool advancing)
  {
    ((WbPluginSQLSynchronize*)_form)->get_be()->set_option("InputFileName1", _in_entry.get_string_value());
    
    values().gset("InputPath", _in_entry.get_string_value());
    values().gset("OutputPath", _out_entry.get_string_value());
    
    grt::Module *module= ((WizardPlugin*)_form)->module();
      
    module->set_document_data("output_filename", _out_entry.get_string_value());
    module->set_document_data("input_filename", _in_entry.get_string_value());
  }

  virtual bool allow_next()
  {
    return g_file_test(_in_entry.get_string_value().c_str(), (GFileTest)(G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
  }

  virtual bool advance()
  {
    if (_confirmed_overwrite_for != _out_entry.get_string_value() && !FsObjectSelector::check_and_confirm_file_overwrite(&_out_entry))
      return false;
    
    _confirmed_overwrite_for= _out_entry.get_string_value();
    
    return WizardPage::advance();
  }
  
protected:
//  Panel _options;
  std::string _confirmed_overwrite_for;
  Table _options_box;

  Label _in_label;
  Label _in_descr;
  TextEntry _in_entry;
  Button _in_button;
  FsObjectSelector* _in_selector;

  Label _out_label;
  Label _out_descr;
  TextEntry _out_entry;
  Button _out_button;
  Label _skip_out_label;
  FsObjectSelector* _out_selector;
};



class PreviewScriptPage : public ViewTextPage
{
public:
  PreviewScriptPage(WizardForm *form)
  : ViewTextPage(form, "preview", (ViewTextPage::Buttons)(ViewTextPage::CopyButton|ViewTextPage::SaveButton), "SQL Scripts (*.sql)|*.sql")
  {
    set_title(_("Review Generated SQL Script"));
    set_short_title(_("Review Script"));
    
    set_editable(true);
  }


  virtual void enter(bool advancing)
  {
    if (advancing)
      set_text(((WbPluginSQLSynchronize*)_form)->get_be()->generate_diff_tree_script());
  }


  virtual bool advance()
  {
    _form->grtm()->push_status_text(_("Updating model catalog..."));
    _form->grtm()->get_grt()->send_info(_("Updating model catalog..."));
    ((WbPluginSQLSynchronize*)_form)->get_be()->apply_changes_to_model();
    _form->grtm()->replace_status_text(_("Model updated."));
    
    std::string path= values().get_string("OutputPath");
    if (!path.empty())
    {
      _form->grtm()->replace_status_text(_("Saving script..."));
      save_text_to(path);
      
      _form->grtm()->replace_status_text(base::strfmt(_("Wrote ALTER Script to '%s'"), path.c_str()));
      _form->grtm()->get_grt()->send_info(base::strfmt(_("Wrote ALTER Script to '%s'"), path.c_str()));
    }
    return true;
  }
  
  virtual std::string next_button_caption()
  {
    return execute_caption();
  }
  
  virtual bool next_closes_wizard() { return true; }
};


class DifferencesPage : SynchronizeDifferencesPage
{
public:
  DifferencesPage(WizardForm *form, DbMySQLScriptSync *be)
  : SynchronizeDifferencesPage(form, be)
  {
    set_title(_("Select How to Apply Changes to Model and Script"));
  }
};

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------


WbPluginSQLSynchronize::WbPluginSQLSynchronize(grt::Module *module)
    : WizardPlugin(module), _be(grtm())
{  
  set_title(_("Script Synchronization - Generate an ALTER Script"));


  add_page(mforms::manage(new ExportInputPage(this)));
  add_page(mforms::manage(new SynchronizeDifferencesPage(this, &_be)));

  add_page(mforms::manage(new PreviewScriptPage(this)));
}


}


grtui::WizardPlugin *createSynchronizeScriptWizard(grt::Module *module, db_CatalogRef catalog)
{
  return new ScriptSynchronize::WbPluginSQLSynchronize(module);
}

void deleteSynchronizeScriptWizard(grtui::WizardPlugin *plugin)
{
    delete plugin;
}