#include "multi_view.h"


#define HORIZONTAL_LAYOUT_ITEM_WIDTH 200
#define VERTICAL_LAYOUT_ITEM_WIDTH 100


MultiView::MultiView(bool tree_view, bool icon_view)
  : Gtk::VBox(false, 0)
{
  if (tree_view)
  {
    _tree_view= Gtk::manage(new Gtk::TreeView());
    pack_start(*_tree_view, false, false);

    _tree_view->signal_row_activated().connect(sigc::mem_fun(this, &MultiView::tree_row_activated));
    _tree_view->signal_button_release_event().
      connect_notify(sigc::mem_fun(*this, &MultiView::tree_button_release_event));

    _selection = _tree_view->get_selection();
    _selection->signal_changed().connect(sigc::mem_fun(this, &MultiView::tree_selection_changed));
    //TODO: There was a possible leak when connecting signal by _tree_view->get_selection()->signal_changed().connect(sigc::mem_fun(this, &MultiView::tree_selection_changed));
    //TODO: Check if it still leaks after selection is moved to explicit member variable
    //TODO: Try to disconnect signal in dtor
  }
  else
    _tree_view= 0;


  if (icon_view)
  {
    _icon_view= Gtk::manage(new EditableIconView());
    pack_start(*_icon_view, false, false);
    _icon_view->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
    _icon_view->set_selection_mode(Gtk::SELECTION_MULTIPLE);
    _icon_view->set_item_width(HORIZONTAL_LAYOUT_ITEM_WIDTH);
    _icon_view->set_row_spacing(0);

    _icon_view->signal_item_activated().connect(sigc::mem_fun(this, &MultiView::icon_activated));
    _icon_view->signal_button_release_event().
      connect_notify(sigc::mem_fun(*this, &MultiView::icon_button_release_event));
    _icon_view->signal_selection_changed().connect(sigc::mem_fun(this, &MultiView::icon_selection_changed));
  }
  else
    _icon_view= 0;
  
  if (tree_view)
    //_tree_view->show();
    set_icon_mode(false);
  else if (icon_view)
    set_icon_mode(true);
    //_icon_view->show();
}


MultiView::~MultiView()
{
}


void MultiView::set_icon_mode(bool flag, bool horizontal_icons)
{
  if (_tree_view && _icon_view)
  {
    if (flag)
    {
      _tree_view->hide();
      _icon_view->show();

      _icon_view->set_orientation(horizontal_icons ? Gtk::ORIENTATION_HORIZONTAL : Gtk::ORIENTATION_VERTICAL);
      
      if (horizontal_icons)
        _icon_view->set_item_width(HORIZONTAL_LAYOUT_ITEM_WIDTH);
      else
        _icon_view->set_item_width(VERTICAL_LAYOUT_ITEM_WIDTH);
    }
    else
    {
      _tree_view->show();
      _icon_view->hide();
    }
  }
  else if (_icon_view)
    _icon_view->set_orientation(horizontal_icons ? Gtk::ORIENTATION_HORIZONTAL : Gtk::ORIENTATION_VERTICAL);
}


void MultiView::set_tree_model(const Glib::RefPtr<TreeModelWrapper> &model)
{
  _tv_model= model;
  
  if (_tree_view)
    _tree_view->set_model(model);
}

void MultiView::set_icon_model(const Glib::RefPtr<TreeModelWrapper> &model)
{
  _iv_model= model;
  
  if (_icon_view)
    _icon_view->set_model(model);
}

void MultiView::unset_models()
{
  if (_icon_view)
    _icon_view->unset_model();
  if (_tree_view)
    _tree_view->unset_model();
}

void MultiView::select_node(const bec::NodeId& node)
{
  Gtk::TreeModel::Path path = node2path(node);

  if (_tree_view)
    _tree_view->set_cursor(path);
  if (_icon_view)
    _icon_view->select_path(path);
}


void MultiView::refresh()
{
 if (_tree_view)
  {
    bec::ListModel* m = _tv_model->get_be_model();
    _tv_model->set_be_model(0);
    _tree_view->unset_model();
    _tree_view->set_model(_tv_model);

    _tv_model->set_be_model(m);
    //_model->refresh(); // TODO: this call is useless as OverviewBE::refresh is empty/commented out
    _tree_view->unset_model();
    _tree_view->set_model(_tv_model);
  }
  if (_icon_view)
  {
    _icon_view->set_model(Glib::RefPtr<ListModelWrapper>());
    _icon_view->set_model(_iv_model);
  }
}


void MultiView::tree_row_activated(const Gtk::TreeModel::Path &path,
                                   const Gtk::TreeViewColumn  *column)
{
  _activate_item(path);
}


void MultiView::icon_activated(const Gtk::TreeModel::Path &path)
{
  _activate_item(path);
}



void MultiView::icon_button_release_event(GdkEventButton* event)
{
  if ( GDK_BUTTON_RELEASE == event->type && 3 == event->button )
  {
    Gtk::TreeModel::Path path;
    
    if (_icon_view->get_item_at_pos(event->x, event->y, path))
      _icon_view->select_path(path);
    
    std::vector<Gtk::TreeModel::Path> selected_items = _icon_view->get_selected_items();
    if ( selected_items.size() > 0 )
    {
      _popup_menu.emit(selected_items[0], event->time);
      return;
    }

    _popup_menu.emit(Gtk::TreeModel::Path(), event->time);
  }
}


void MultiView::tree_button_release_event(GdkEventButton* event)
{
  if ( GDK_BUTTON_RELEASE == event->type && 3 == event->button )
  {
    Glib::RefPtr<Gtk::TreeView::Selection> selection= _tree_view->get_selection();
    
    if ( selection->count_selected_rows() > 0 )
    {
      std::vector<Gtk::TreeModel::Path> selected= selection->get_selected_rows();
      _popup_menu.emit(selected[0], event->time);
    }
    _popup_menu.emit(Gtk::TreeModel::Path(), event->time);
  }
}

void MultiView::on_selection_changed(const std::vector<bec::NodeId>& sel)
{}

void MultiView::icon_selection_changed()
{
  const std::vector<Gtk::TreeModel::Path> paths = _icon_view->get_selected_items();
  std::vector<bec::NodeId> nodes;

  const int paths_size = paths.size();
  for ( int i = 0; i < paths_size; ++i )
    nodes.push_back(_iv_model->get_node_for_path(paths[i]));

  on_selection_changed(nodes);
  _selection_changed.emit(nodes);
}


void MultiView::tree_selection_changed()
{
  const std::vector<Gtk::TreeModel::Path> paths = _tree_view->get_selection()->get_selected_rows();
  std::vector<bec::NodeId> nodes;

  const int paths_size = paths.size();
  for ( int i = 0; i < paths_size; ++i )
    nodes.push_back(_tv_model->get_node_for_path(paths[i]));

  on_selection_changed(nodes);
  _selection_changed.emit(nodes);
}


Gtk::TreeModel::Path MultiView::get_selected()
{
  if (_icon_view && _icon_view->is_visible())
  {
    std::vector<Gtk::TreeModel::Path> selected_items = _icon_view->get_selected_items();
    if ( selected_items.size() > 0 )
      return selected_items[0];
  }
  
  if (_tree_view && _tree_view->is_visible())
  {
    Glib::RefPtr<Gtk::TreeView::Selection> selection= _tree_view->get_selection();

    if ( selection->count_selected_rows() > 0 )
    {
      std::vector<Gtk::TreeModel::Path> selected= selection->get_selected_rows();
      return selected[0];
    }
  }
  
  return Gtk::TreeModel::Path();
}
