#include "layer_tree.h"
#include "treemodel_wrapper.h"
#include "image_cache.h"
#include "model/wb_layer_tree.h"
#include "model/wb_model_diagram_form.h"
#include "base/string_utilities.h"
#include "linux_utilities/gtk_helpers.h"


LayerTree::LayerTree(wb::WBContextUI *wbui)
  : _wbui(wbui)
  , _diagram_form(0)
  , _column(0)
  , _pending_refresh(false)
{
  set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
  add(_tree);
  set_shadow_type(Gtk::SHADOW_IN);
  _tree.set_headers_visible(true);

  show_all();

  _tree.signal_row_activated().connect(sigc::mem_fun(this, &LayerTree::activate_row));
}

LayerTree::~LayerTree()
{
  _model->invalidate();
  delete _column;
}

void LayerTree::set_model(wb::ModelDiagramForm *model)
{
  _diagram_form = model;
  _layer_tree= model->get_layer_tree();

  if (!_model)
  {
    _column= new Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> >();
    Gtk::TreeViewColumn *vcolumn= Gtk::manage(new Gtk::TreeViewColumn(""));

    Gtk::CellRendererPixbuf *prend= Gtk::manage(new Gtk::CellRendererPixbuf());
    vcolumn->pack_start(*prend, true);
    
    _model= TreeModelWrapper::create(_layer_tree, &_tree, "LayerTree", bec::NodeId(0));
    _model->model().add_generic_column(-1, _column, vcolumn);
    _model->model().append_string_column(bec::ValueTreeBE::Name, "", RO, WITH_ICON);
    _model->set_expanded_rows_storage(&_expanded_rows);
    _tree.set_model(_model);
    _tree.set_headers_visible(false);

    vcolumn->add_attribute(prend->property_pixbuf(), *_column);

    _model->set_fake_column_value_getter(sigc::mem_fun(this, &LayerTree::get_tree_value));
    
    scoped_connect(_layer_tree->tree_changed_signal(),sigc::mem_fun(this, &LayerTree::tree_changed));
  }
}


void LayerTree::tree_changed(const bec::NodeId &row, int old_count)
{
  if (!_pending_refresh)
    Glib::signal_idle().connect(sigc::bind_return(sigc::mem_fun(this, &LayerTree::refresh), false));
  _pending_refresh = true;
}


void LayerTree::refresh()
{
  _pending_refresh = false;
  if (!_selected_icon)
  {
    _selected_icon= ImageCache::get_instance()->image_from_filename("layer_selected.png", false);
    _unselected_icon= ImageCache::get_instance()->image_from_filename("layer_unselected.png", false);
    _mixed_icon= ImageCache::get_instance()->image_from_filename("layer_mixed.png", false);
  }

  Gtk::TreePath first_row, last_row;
  std::list<Gtk::TreePath> selected(_tree.get_selection()->get_selected_rows());

  _tree.get_visible_range(first_row, last_row);

  freeze_notify();
  _tree.freeze_notify();  

  _tree.unset_model();
  _layer_tree->refresh();
  _tree.set_model(_model);

  reexpand_nodes();

  if (!first_row.empty())
    _tree.scroll_to_row(first_row);

  for (std::list<Gtk::TreePath>::const_iterator path = selected.begin(); path != selected.end(); ++path)
    _tree.get_selection()->select(*path);

  _tree.thaw_notify();
  thaw_notify();
}


void LayerTree::reexpand_nodes()
{
  expand_tree_nodes_as_in_be(_model, &_tree);
}


void LayerTree::get_tree_value(const Gtk::TreeModel::iterator &iter, int column, GType type, Glib::ValueBase& value)
{
  bec::NodeId node= _model->node_for_iter(iter);
  std::string sel;

  _layer_tree->get_field(node, wb::LayerTreeBE::Selected, sel);

  g_value_init(value.gobj(), GDK_TYPE_PIXBUF);

  if (sel == "")
    g_value_set_object(value.gobj(), _unselected_icon->gobj());
  else if (sel == "X")
    g_value_set_object(value.gobj(), _selected_icon->gobj());
  else
    g_value_set_object(value.gobj(), _mixed_icon->gobj());
}



void LayerTree::activate_row(const Gtk::TreePath &path, Gtk::TreeViewColumn *column)
{
  bec::NodeId node= _model->node_for_iter(_model->get_iter(path));

  _layer_tree->activate_node(node);
}
