#include "stdafx.h"

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

#include "grtui/grtdb_object_filter.h"

#include "db_mysql_sql_export.h"


using namespace grtui;
using namespace mforms;


class ExportInputPage : public WizardPage
{
public:
  ExportInputPage(WizardPlugin *form)
    : WizardPage(form, "options"), _options(mforms::TitledBoxPanel), _options_box(false)
  {
    set_title(_("SQL Export Options"));
    set_short_title(_("SQL Export Options"));

    _contents.set_row_count(2);
    _contents.set_column_count(3);
    _contents.set_column_spacing(8);
    _contents.set_row_spacing(8);
    
    _contents.add(&_caption, 0, 1, 0, 1, mforms::HFillFlag);
    _contents.add(&_filename, 1, 2, 0, 1, mforms::HFillFlag|mforms::HExpandFlag);
    _contents.add(&_browse_button, 2, 3, 0, 1, mforms::HFillFlag);
    _contents.add(&_skip_out_label, 1, 2, 1, 2, 0);
    
    _skip_out_label.set_text(_("Leave blank to view generated script but not save to a file."));
    _skip_out_label.set_style(SmallHelpTextStyle);
    
    enable_file_browsing(&_filename, &_browse_button, mforms::SaveFile, "SQL Files (*.sql)|*.sql");
    
    _caption.set_text(_("Output SQL Script File:"));
    _browse_button.set_text(_("Browse..."));

    _filename.signal_changed().connect(sigc::mem_fun(this, &ExportInputPage::file_changed));

    add(&_contents, false, true);
    
    
    _options.set_title(_("SQL Options"));
    
    _options.add(&_options_box);
    _options_box.set_padding(12);
    _options_box.set_spacing(8);
    
    _generate_drop_check.set_text(_("Generate DROP Statements Before Each CREATE Statement"));
    _options_box.add(&_generate_drop_check, false, false);
    _generate_drop_schema_check.set_text(_("Generate DROP SCHEMA"));
    _options_box.add(&_generate_drop_schema_check, false, false);
    _skip_foreign_keys_check.set_text(_("Skip Creation of FOREIGN KEYS"));
    _options_box.add(&_skip_foreign_keys_check, false, false);
    _omit_schema_qualifier_check.set_text(_("Omit Schema Qualifier in Object Names"));
    _options_box.add(&_omit_schema_qualifier_check, false, false);
    _generate_create_index_check.set_text(_("Generate Separate CREATE INDEX Statements"));
    _options_box.add(&_generate_create_index_check, false, false);
    _generate_show_warnings_check.set_text(_("Add SHOW WARNINGS After Every DDL Statement"));
    _options_box.add(&_generate_show_warnings_check, false, false);
    _skip_users_check.set_text(_("Do Not Create Users. Only Export Privileges"));
    _options_box.add(&_skip_users_check, false, false);
    _generate_insert_check.set_text(_("Generate INSERT Statements for Tables"));
    _options_box.add(&_generate_insert_check, false, false);

    add(&_options, false, false);
    
    _filename.set_value(form->module()->document_string_data("output_filename", ""));
    _generate_drop_check.set_active(form->module()->document_int_data("generate_drop", false));
    _generate_drop_schema_check.set_active(form->module()->document_int_data("generate_schema_drop", 0));
    _skip_foreign_keys_check.set_active(form->module()->document_int_data("skip_foreign_keys", false));
    _omit_schema_qualifier_check.set_active(form->module()->document_int_data("omit_schema_qualifier", false));
    _generate_create_index_check.set_active(form->module()->document_int_data("generate_create_index", false));
    _generate_show_warnings_check.set_active(form->module()->document_int_data("generate_show_warnings", false));
    _skip_users_check.set_active(form->module()->document_int_data("skip_users", false));
    _generate_insert_check.set_active(form->module()->document_int_data("generate_insert", false));
  }
  

  void file_changed()
  {
    validate();
  }

  virtual bool allow_next()
  {
    return true;
    //return !_filename.get_string_value().empty();
  }
  
  virtual bool advance()
  {
    if (_confirmed_overwrite_for != _filename.get_string_value() && !check_and_confirm_file_overwrite(&_filename))
      return false;
    _confirmed_overwrite_for= _filename.get_string_value();
    
    return WizardPage::advance();
  }

  virtual void leave(bool advancing)
  {
    if (advancing)
    {
      values().gset("OutputFileName", _filename.get_string_value());
    
      values().gset("GenerateDrops", _generate_drop_check.get_active());
      values().gset("GenerateSchemaDrops", _generate_drop_schema_check.get_active());
      values().gset("SkipForeignKeys", _skip_foreign_keys_check.get_active());
      values().gset("GenerateWarnings", _generate_show_warnings_check.get_active());
      values().gset("GenerateCreateIndex", _generate_create_index_check.get_active());
      values().gset("NoUsersJustPrivileges", _skip_users_check.get_active());
      values().gset("GenerateInserts", _generate_insert_check.get_active());
      values().gset("OmitSchemata", _omit_schema_qualifier_check.get_active());

      grt::Module *module= ((WizardPlugin*)_form)->module();
      
      module->set_document_data("output_filename", _filename.get_string_value());
      module->set_document_data("generate_drop", _generate_drop_check.get_active());
      module->set_document_data("generate_schema_drop", _generate_drop_schema_check.get_active());
      module->set_document_data("skip_foreign_keys", _skip_foreign_keys_check.get_active());
      module->set_document_data("omit_schema_qualifier", _omit_schema_qualifier_check.get_active());
      module->set_document_data("generate_create_index", _generate_create_index_check.get_active());
      module->set_document_data("generate_show_warnings", _generate_show_warnings_check.get_active());
      module->set_document_data("skip_users", _skip_users_check.get_active());
      module->set_document_data("generate_insert", _generate_insert_check.get_active());
    }
  }

protected:
  std::string _confirmed_overwrite_for;
  
  Table _contents;
  Label _caption;
  TextEntry _filename;
  Button _browse_button;
  Label _skip_out_label;

  Panel _options;
  Box _options_box;

  CheckBox _generate_drop_check;
  CheckBox _generate_drop_schema_check;
  CheckBox _skip_foreign_keys_check;
  CheckBox _generate_create_index_check;
  CheckBox _generate_show_warnings_check;
  CheckBox _skip_users_check;
  CheckBox _generate_insert_check;
  CheckBox _omit_schema_qualifier_check;
};

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


class ExportFilterPage : public WizardObjectFilterPage
{
public:
  ExportFilterPage(WizardPlugin *form, DbMySQLSQLExport *export_be)
    : WizardObjectFilterPage(form, "filter"), _export_be(export_be)
  {    
    _table_filter= 0;
    _view_filter= 0;
    _routine_filter= 0;
    _trigger_filter= 0;
    _user_filter= 0;
    
    set_title(_("SQL Object Export Filter"));
    set_short_title(_("Filter Objects"));

    _top_label.set_wrap_text(true);
    _top_label.set_text(_("To exclude objects of a specific type from the SQL Export, disable the corresponding checkbox. "
                        "Press Show Filter and add objects or patterns to the ignore list to exclude them from the export."));
  }

protected:
  virtual void enter(bool advancing)
  {
    if (advancing && !_table_filter)
      setup_filters();
    
    WizardObjectFilterPage::enter(advancing);
  }
  
  
  void setup_filters()
  {
    bec::GrtStringListModel *users_model;
    bec::GrtStringListModel *users_imodel;
    bec::GrtStringListModel *tables_model;
    bec::GrtStringListModel *tables_imodel;
    bec::GrtStringListModel *views_model;
    bec::GrtStringListModel *views_imodel;
    bec::GrtStringListModel *routines_model;
    bec::GrtStringListModel *routines_imodel;
    bec::GrtStringListModel *triggers_model;
    bec::GrtStringListModel *triggers_imodel;

    _export_be->setup_grt_string_list_models_from_catalog(&users_model, &users_imodel, 
                                                       &tables_model, &tables_imodel,
                                                       &views_model, &views_imodel, 
                                                       &routines_model, &routines_imodel, 
                                                       &triggers_model, &triggers_imodel);
    

    _table_filter= add_filter(db_mysql_Table::static_class_name(),
                              _("Export %s Objects"),
                              tables_model, tables_imodel);
    _view_filter= add_filter(db_mysql_View::static_class_name(),
                             _("Export %s Objects"),
                             views_model, views_imodel);

    _routine_filter= add_filter(db_mysql_Routine::static_class_name(),
                                _("Export %s Objects"),
                                routines_model, routines_imodel);

    _trigger_filter= add_filter(db_mysql_Trigger::static_class_name(),
                                _("Export %s Objects"),
                                triggers_model, triggers_imodel);

    _user_filter= add_filter(db_User::static_class_name(),
                             _("Export %s Objects"),
                             users_model, users_imodel);
  }


  virtual bool advance()
  {
    _export_be->set_option("OutputFileName", values().get_string("OutputFileName"));
    _export_be->set_option("GenerateDrops", values().get_int("GenerateDrops"));
    _export_be->set_option("SkipForeignKeys", values().get_int("SkipForeignKeys"));
    _export_be->set_option("GenerateWarnings", values().get_int("GenerateWarnings"));
    _export_be->set_option("GenerateCreateIndex", values().get_int("GenerateCreateIndex"));
    _export_be->set_option("NoUsersJustPrivileges", values().get_int("NoUsersJustPrivileges"));
    _export_be->set_option("GenerateInserts", values().get_int("GenerateInserts"));
    _export_be->set_option("OmitSchemata", values().get_int("OmitSchemata"));

    _export_be->set_option("TablesAreSelected", _table_filter->get_active());
    _export_be->set_option("TriggersAreSelected", _trigger_filter->get_active());
    _export_be->set_option("RoutinesAreSelected", _routine_filter->get_active());
    _export_be->set_option("ViewsAreSelected", _view_filter->get_active());
    _export_be->set_option("UsersAreSelected", _user_filter->get_active());

    return true;
  }


protected:
  DbMySQLSQLExport *_export_be;
  DBObjectFilterFrame *_table_filter;
  DBObjectFilterFrame *_view_filter;
  DBObjectFilterFrame *_routine_filter;
  DBObjectFilterFrame *_trigger_filter;
  DBObjectFilterFrame *_user_filter;
};



class PreviewScriptPage : public ViewTextPage
{
  DbMySQLSQLExport *_export_be;
  mforms::Label _label;
  
public:
  PreviewScriptPage(WizardPlugin *form, DbMySQLSQLExport *export_be)
  : ViewTextPage(form, "preview", (ViewTextPage::Buttons)(ViewTextPage::CopyButton|ViewTextPage::SaveButton), "SQL Scripts (*.sql)|*.sql"), _export_be(export_be)
  {
    set_title(_("Review Generated Script"));
    set_short_title(_("Review SQL Script"));
    
    _save_button.set_text(_("Save to Other File..."));
    _save_button.set_tooltip(_("Save the script to a file."));
    
    add(&_label, false, true);
    _label.set_style(mforms::WizardHeadingStyle);
        
    set_editable(true);
  }
  
  
  virtual void enter(bool advancing)
  {
    if (advancing)
    {
      if (_export_be->get_output_filename().empty())
        _label.set_text(_("Review the generated script."));
      else
        _label.set_text(_("Review and edit the generated script and press Finish to save."));
      
      
      try
      {
        _export_be->start_export(true);
        
        set_text(_export_be->export_sql_script());
        
        _form->clear_problem();
      }
      catch (std::exception &exc)
      {
        set_text(std::string(_("Could not generate CREATE script.")).append("\n").append(exc.what()));
        _form->set_problem(_("Error generating script."));
      }
    }
  }
  
  
  virtual bool advance()
  {
    std::string path= values().get_string("OutputFileName");
    if (!path.empty())
    {
      save_text_to(path);
      
      _form->grtm()->push_status_text(strfmt(_("Wrote CREATE Script to '%s'"), path.c_str()));
      _form->grtm()->get_grt()->send_info(strfmt(_("Wrote CREATE Script to '%s'"), path.c_str()));
    }
    return true;
  }
  
  virtual std::string next_button_caption()
  {
    return finish_caption();
  }
  
  virtual bool next_closes_wizard() { return true; }
};


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

class WbPluginSQLExport : public WizardPlugin
{
  DbMySQLSQLExport _export_be;
  
public:
  WbPluginSQLExport(grt::Module *module)
    : WizardPlugin(module), _export_be(grtm())
  {
    add_page(new ExportInputPage(this));
    add_page(new ExportFilterPage(this, &_export_be));
    add_page(new PreviewScriptPage(this, &_export_be));
    
    set_title(_("Forward Engineer SQL Script"));
  }
};


grtui::WizardPlugin *createExportCREATEScriptWizard(grt::Module *module, db_CatalogRef catalog)
{
  return new WbPluginSQLExport(module);
}

