#include "catalog_tree.h"
#include "treemodel_wrapper.h"
#include "gtk_helpers.h"

#include "grtdb/db_object_helpers.h"
#include "workbench/wb_component_physical.h"


CatalogTree::CatalogTree(wb::WBContextUI *wbui)
  : _wbui(wbui)
{
  set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
  _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
  add(_tree);
  set_shadow_type(Gtk::SHADOW_IN);
  _tree.set_headers_visible(false);

  std::vector<Gtk::TargetEntry> drag_types;
  drag_types.push_back(Gtk::TargetEntry(WB_DBOBJECT_DRAG_TYPE, Gtk::TARGET_SAME_APP));
  
  _tree.enable_model_drag_source(drag_types, Gdk::MODIFIER_MASK, Gdk::ACTION_COPY);
  //_tree.enable_drag_source_set(drag_types);
  _tree.signal_drag_begin().connect(sigc::mem_fun(this, &CatalogTree::drag_begin));
  _tree.signal_drag_data_get().connect(sigc::mem_fun(this, &CatalogTree::drag_data_get));
  
  show_all();
}


void CatalogTree::refresh()
{
  if (!_model)
  {
    _model= TreeModelWrapper::create(_wbui->get_catalog_tree(), &_tree, "CatalogTree", bec::NodeId(0));
    _model->model().append_string_column(bec::ValueTreeBE::Name, _("Name"), EDITABLE, WITH_ICON);
    _tree.set_model(_model);
    _model->set_expanded_rows_storage(&_expanded_rows);
    _model->set_fe_menu_handler(sigc::mem_fun(this, &CatalogTree::handle_menu));
  }
  else
  {
    bec::ListModel* m = _model->get_be_model();
    _model->set_be_model(0);
    _tree.unset_model();
    _tree.set_model(_model);

    _model->set_be_model(m);
    _tree.unset_model();
    _model->refresh();
    //_wbui->get_catalog_tree()->refresh();
    _tree.set_model(_model);
  }
  
  reexpand_nodes();
}


bool CatalogTree::reexpand_node(const Gtk::TreePath &path)
{
  if (_wbui->get_catalog_tree()->is_expanded(_model->get_node_for_path(path)) || path.get_depth() <= 2)
    _tree.expand_to_path(path);

  return true;
}


void CatalogTree::reexpand_nodes()
{
  expand_tree_nodes_as_in_be(_model, &_tree);
  //_model->foreach_path(sigc::mem_fun(this, &CatalogTree::reexpand_node));
}



void CatalogTree::drag_begin(const Glib::RefPtr<Gdk::DragContext> &context)
{
  
}


void CatalogTree::drag_data_get(const Glib::RefPtr<Gdk::DragContext> &context,
                                Gtk::SelectionData &selection, guint , guint)
{ 
  std::string data;
  std::list<db_DatabaseObjectRef> objects;
  
  
  std::list<Gtk::TreePath> rows(_tree.get_selection()->get_selected_rows());

  if (rows.size() > 0)
  {
    for (std::list<Gtk::TreePath>::const_iterator iter= rows.begin(); iter != rows.end(); ++iter)
    {
      bec::NodeId node(_model->node_for_iter(_model->get_iter(*iter)));

      grt::ValueRef value(_wbui->get_catalog_tree()->get_node_value(node));

      if (value.is_valid() && db_DatabaseObjectRef::can_wrap(value))
        objects.push_back(db_DatabaseObjectRef::cast_from(value));
    }
  
    if (!objects.empty())
    {
      std::string data= bec::CatalogHelper::dbobject_list_to_dragdata(objects);
      selection.set(selection.get_target(), data);
    }
  }
}


void CatalogTree::handle_menu(const std::string& name, const std::vector<bec::NodeId>& nodes)
{
  if (name == "refreshCatalog")
    refresh();
  else if (name == "renameItem")
  {
    Gtk::TreeModel::Path  path;
    Gtk::TreeViewColumn  *col(0);
    
    _tree.get_cursor(path, col);
  
    if (!path.empty() && col)
      _tree.set_cursor(path, *col, true);
  }
}

