
#include "mforms/grttreeview.h"

class SynchronizeDifferencesPage : public WizardPage
{
  DbMySQLScriptSync *_be;
  sigc::slot<db_CatalogRef> get_source_catalog;

public:
  SynchronizeDifferencesPage(WizardForm *form, DbMySQLScriptSync *be)
    : WizardPage(form, "diffs"), _be(be), _tree(true), _bottom_box(true)
  {    
    set_title(_("Choose Direction to Apply Changes"));
    set_short_title(_("Select Changes to Apply"));

    _heading.set_wrap_text(true);
    _heading.set_text(_("Double click arrows in the list to choose whether to ignore changes, update "
      "the model with database changes or vice-versa. You can also apply an action to multiple selected rows."));
    add(&_heading, false, true);
    
    add(&_tree, true, true);
    _tree.set_allow_multi_selection(true);
    
    add(&_bottom_box, false, false);
    
    _bottom_box.set_spacing(12);

    _update_model.set_text(_("Update Model"));
    _update_model.set_tooltip(_("Update the model with changes detected in database/script."));
    _skip.set_text(_("Ignore"));
    _skip.set_tooltip(_("Ignore the change and do not update neither the database/script or the model."));
    _update_source.set_text(_("Update Source"));
    _update_source.set_tooltip(_("Update the database/script with changes detected in the model."));

    _bottom_box.add(&_update_model, false, true);
    _bottom_box.add(&_skip, false, true);
    _bottom_box.add(&_update_source, false, true);

    _update_source.signal_clicked().connect(sigc::mem_fun(this, &SynchronizeDifferencesPage::update_source));
    _update_model.signal_clicked().connect(sigc::mem_fun(this, &SynchronizeDifferencesPage::update_model));
    _skip.signal_clicked().connect(sigc::mem_fun(this, &SynchronizeDifferencesPage::update_none));
    
    _tree.add_column(mforms::IconStringGRTColumnType,
                     DiffTreeBE::ModelObjectName,
                     _("Model"));
    _tree.add_column(mforms::IconGRTColumnType,
                     DiffTreeBE::ApplyDirection,
                     _("Update"));
    _tree.add_column(mforms::IconStringGRTColumnType,
                     DiffTreeBE::DbObjectName,
                     _("Source"));
    
    _tree.set_column_width(1, 50);

    _tree.signal_row_activate().connect(sigc::mem_fun(this, &SynchronizeDifferencesPage::activate_row));
  }


  void activate_row(const bec::NodeId &node, int column)
  {
    if (column == DiffTreeBE::ApplyDirection)
    {
      _be->set_next_apply_direction(node);
      _tree.refresh(node);
    }
  }
  
  void set_source_catalog_slot(const sigc::slot<db_CatalogRef> &source_catalog_slot)
  {
    get_source_catalog= source_catalog_slot;
  }


  virtual bool pre_load()
  {
    bec::TreeModel *diff_tree= _be->init_diff_tree(std::vector<std::string>(),
                                                   get_source_catalog ? get_source_catalog() : db_CatalogRef(),
                                                   db_CatalogRef());

    _tree.set_model(diff_tree);
    
    return true;
  }

  
  void update_source()
  {
    std::vector<bec::NodeId> nodes;
    if (_tree.get_selection(nodes) > 0)
    {
      bool refresh_individual_nodes= nodes.size() < 50;

      for (std::vector<bec::NodeId>::const_iterator iter= nodes.begin(); iter != nodes.end(); ++iter)
      {
        _be->set_apply_direction(*iter, DiffNode::ApplyToDb);
        if (refresh_individual_nodes)
          _tree.refresh(*iter);
      }
      if (!refresh_individual_nodes)
        _tree.refresh(bec::NodeId());
    }
  }
  
  void update_model()
  {
    std::vector<bec::NodeId> nodes;
    if (_tree.get_selection(nodes) > 0)
    {
      bool refresh_individual_nodes= nodes.size() < 50;

      for (std::vector<bec::NodeId>::const_iterator iter= nodes.begin(); iter != nodes.end(); ++iter)
      {
        _be->set_apply_direction(*iter, DiffNode::ApplyToModel);
        if (refresh_individual_nodes)
          _tree.refresh(*iter);
      }    
      if (!refresh_individual_nodes)
        _tree.refresh(bec::NodeId());
    }
  }
  
  void update_none()
  { 
    std::vector<bec::NodeId> nodes;
    if (_tree.get_selection(nodes) > 0)
    {
      bool refresh_individual_nodes= nodes.size() < 50;

      for (std::vector<bec::NodeId>::const_iterator iter= nodes.begin(); iter != nodes.end(); ++iter)
      {
        _be->set_apply_direction(*iter, DiffNode::DontApply);
        if (refresh_individual_nodes)
          _tree.refresh(*iter);
      }
      if (!refresh_individual_nodes)
        _tree.refresh(bec::NodeId());
    }
  }
  
protected:
  GRTTreeView _tree;
  Label _heading;
  
  Box _bottom_box;
  Button _select_all;
  Button _select_children;
  Button _update_source;
  Button _update_model;
  Button _skip;
};

