/* 
 * 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_view_text_page.h"

#include "db_mysql_diff_reporting.h"
#include "db.mysql/backend/db_plugin_be.h"
#include "base/string_utilities.h"
#include "mforms/fs_object_selector.h"

using namespace grtui;
using namespace mforms;
using namespace base;

#include "diff_source_select_page.h"

#include "grtui/connection_page.h"
#include "db.mysql/frontend/schema_selection_page.h"
#include "db.mysql/frontend/fetch_schema_names_page.h"
#include "db.mysql/frontend/fetch_schema_contents_page.h"

  
class ViewResultPage : public ViewTextPage
{
public:
  ViewResultPage(WizardForm *form)
    : ViewTextPage(form, "viewdiff", (ViewTextPage::Buttons)(ViewTextPage::SaveButton|ViewTextPage::CopyButton), "Text Files (*.txt)|*.txt")
  {
    set_short_title(_("Differences Report"));
    set_title(_("Differences Found in Catalog Comparison"));
  }

  void set_generate_text_slot(const boost::function<std::string ()> &slot)
  {
    _generate= slot;
  }

  virtual void enter(bool advancing)
  {
    if (advancing)
      _text.set_value(_generate());
  }

  virtual bool allow_cancel() { return false; }
  virtual bool next_closes_wizard() { return true; }

protected:  
  boost::function<std::string ()> _generate;
};


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

class WbPluginDiffReport : public WizardPlugin
{
public:
  WbPluginDiffReport(grt::Module *module)
    : WizardPlugin(module), _be(grtm())
  {
    add_page(mforms::manage(_source_page= new SourceSelectPage(this)));

    Db_plugin *dbplugin[2];
    _left_db.grtm(grtm());
    _right_db.grtm(grtm());
    
    dbplugin[0]= &_left_db;
    dbplugin[1]= &_right_db;
    
    const char *title_prefix[2];
    title_prefix[0]= _("Left Catalog: ");
    title_prefix[1]= _("Right Catalog: ");

    for (int i= 0; i < 2; i++)
    {
      ConnectionPage *connect;
      add_page(mforms::manage(connect= new ConnectionPage(this, strfmt("connect%i", i).c_str())));
      connect->set_db_connection(dbplugin[i]->db_conn());
      connect->set_title(std::string(title_prefix[i]).append(connect->get_title()));

      FetchSchemaNamesProgressPage *fetch_names_page;
      add_page(mforms::manage(fetch_names_page= new FetchSchemaNamesProgressPage(this, strfmt("fetchNames%i",i).c_str())));
      fetch_names_page->set_db_connection(dbplugin[i]->db_conn());
      fetch_names_page->set_load_schemata_slot(boost::bind(&WbPluginDiffReport::load_schemata, this, dbplugin[i]));
      fetch_names_page->set_title(std::string(title_prefix[i]).append(fetch_names_page->get_title()));

      SchemaSelectionPage *schema_page;
      add_page(mforms::manage(schema_page= new SchemaSelectionPage(this, strfmt("pickSchemata%i", i).c_str())));
      schema_page->set_db_plugin(dbplugin[i]);
      schema_page->set_title(std::string(title_prefix[i]).append(schema_page->get_title()));

      FetchSchemaContentsProgressPage *fetch_schema_page;
      add_page(mforms::manage(fetch_schema_page= new FetchSchemaContentsProgressPage(this, strfmt("fetchSchema%i",i).c_str())));
      fetch_schema_page->set_db_plugin(dbplugin[i]);
      fetch_schema_page->set_title(std::string(title_prefix[i]).append(fetch_schema_page->get_title()));
    }
    
    ViewResultPage *page;
    add_page(mforms::manage(page= new ViewResultPage(this)));
    page->set_generate_text_slot(boost::bind(&WbPluginDiffReport::generate_report, this));

    set_title(_("Compare and Report Differences in Catalogs"));
  }
  
  std::string generate_report()
  {
    db_CatalogRef left_catalog, right_catalog;
    std::string left_file, right_file;

    if (_source_page->get_left_source() == DataSourceSelector::ServerSource)
      left_catalog= _left_db.db_catalog();

    if (_source_page->get_right_source() == DataSourceSelector::ServerSource)
      right_catalog= _right_db.db_catalog();

    left_file= values().get_string("left_source_file");
    right_file= values().get_string("right_source_file");

    std::string report;
    try
    {
      report = _be.generate_report(left_file, right_file, left_catalog, right_catalog);
    }
    catch (const std::exception &exc)
    {
      report = base::strfmt("Error generating report: %s", exc.what());
    }
    return report;
  }


  virtual WizardPage *get_next_page(WizardPage *current)
  {
    std::string curid= current->get_id();
    std::string nextid;
    
    if (curid == "source")
    {
      if (_source_page->get_left_source() == DataSourceSelector::ServerSource)
        nextid= "connect0";
      else if (_source_page->get_right_source() == DataSourceSelector::ServerSource)
        nextid= "connect1";
      else
        nextid= "viewdiff";
    }
    else if (curid == "fetchSchema0")
    {
      if (_source_page->get_right_source() == DataSourceSelector::ServerSource)
        nextid= "connect1";
      else
        nextid= "viewdiff";
    }

    if (!nextid.empty())
      return get_page_with_id(nextid);
    else
      return WizardForm::get_next_page(current);
  }


protected:
  DbMySQLDiffReporting _be;
  Db_plugin _left_db;
  Db_plugin _right_db;
  SourceSelectPage *_source_page;
  
  std::vector<std::string> load_schemata(Db_plugin *db)
  {
    std::vector<std::string> names;
    db->load_schemata(names);
    return names;
  }
};


WizardPlugin *createWbPluginDiffReport(grt::Module *module)
{
  return new WbPluginDiffReport(module);
}

