#include <gtkmm.h>
#include "MGGladeXML.h"
#include "toolbar_manager.h"
#include "workbench/wb_command_ui.h"
#include "image_cache.h"


class ColorComboColumns : public Gtk::TreeModel::ColumnRecord
{
public:
  Gtk::TreeModelColumn<std::string> color;
  Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > image;
  
  ColorComboColumns()
  {
    add(color);
    add(image);
  }
};

static ColorComboColumns *color_combo_columns= 0;

static Gtk::ComboBox *create_color_combo(const std::vector<std::string> &colors, const std::string &selected)
{
  int i= 0;
  if (!color_combo_columns)
  {
    static ColorComboColumns color_combo_columns_instance;
    color_combo_columns= &color_combo_columns_instance;
  }

  Glib::RefPtr<Gtk::ListStore> model= Gtk::ListStore::create(*color_combo_columns);
  Gtk::ComboBox *combo= new Gtk::ComboBox(model);

  combo->pack_start(color_combo_columns->image);

  for (std::vector<std::string>::const_iterator iter= colors.begin();
       iter != colors.end(); ++iter, ++i)
  {
    Gtk::TreeRow row= *model->append();
    Glib::RefPtr<Gdk::Pixbuf> pixbuf;
    Gdk::Color color(*iter);

    combo->get_colormap()->alloc_color(color);
    
    pixbuf= Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, false, 8, 16, 14);
    pixbuf->fill(color.get_pixel()<<8);
    
    row[color_combo_columns->color]= *iter;
    row[color_combo_columns->image]= pixbuf;
    
    if (selected == *iter)
      combo->set_active(i);
  }

  return combo;
}


//------------------------------------------------------------------------------
ToolbarManager::ToolbarManager(wb::CommandUI *be)
  : _be(be)
{}


void ToolbarManager::add_toolbar_item(Gtk::Box* toolbar, const wb::WBToolbarItem& item, bool right)
{
  static ImageCache *images = ImageCache::get_instance();
  Gtk::Widget *w= 0;

  switch ( item.type )
  {
    case wb::ToolbarAction:
    {
      Gtk::Image *img = new Gtk::Image(images->image(item.icon));
      Gtk::Button *btn = new Gtk::Button();
      btn->add(*Gtk::manage(img));
      btn->set_name(item.command);
      btn->set_tooltip_text(item.tooltip);
      btn->set_relief(Gtk::RELIEF_NONE);

      btn->show_all();
        
      btn->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &ToolbarManager::clicked), btn));
      
      w= btn;
      break;
    }

    case wb::ToolbarToggle:
    {
      Gtk::ToggleButton *btn;
      if (item.icon != 0)
      {
        btn= new Gtk::ToggleButton();
        btn->add(*Gtk::manage(new Gtk::Image(images->image(item.icon))));
      }
      else
        btn= new Gtk::CheckButton(item.caption);
      btn->set_name(item.command);
      btn->set_tooltip_text(item.tooltip);
      btn->set_relief(Gtk::RELIEF_NONE);
      btn->set_active(item.checked);

      btn->show_all();

      btn->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &ToolbarManager::clicked), btn));

      w= btn;
      break;
    }

    case wb::ToolbarRadio:
    {
      Gtk::Image *img = new Gtk::Image(images->image(item.icon));
      Gtk::ToggleButton *btn = new Gtk::ToggleButton();
      btn->add(*Gtk::manage(img));
      btn->set_name(item.command);
      if (!item.caption.empty())
        btn->set_label(item.caption);
      btn->set_tooltip_text(item.tooltip);
      btn->set_relief(Gtk::RELIEF_NONE);
      btn->set_active(item.checked);

      btn->show_all();
        
      btn->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &ToolbarManager::clicked), btn));

      w= btn;
      break;
    }
    case wb::ToolbarCheck:
    {
      Gtk::CheckButton *btn = new Gtk::CheckButton(item.caption);
      btn->set_name(item.command);
      btn->set_tooltip_text(item.tooltip);
      btn->set_active(item.checked);

      btn->show_all();

      btn->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &ToolbarManager::toggled), btn, item.name, item.command));

      w= btn;
      break;
    }
    case wb::ToolbarSeparator:
    {
      Gtk::Alignment *align= new Gtk::Alignment(0.5, 0.5);
      Gtk::Separator *sep;

      if (dynamic_cast<Gtk::HBox*>(toolbar))
        sep= new Gtk::VSeparator();
      else
        sep= new Gtk::HSeparator();

      align->set_padding(2, 2, 2, 2);

      sep->show();
      align->add(*Gtk::manage(sep));

      w= align;
      break;
    }
    case wb::ToolbarLabel:
    {
      Gtk::Label *label= new Gtk::Label(item.command, 0.0, 0.5);
      
      w= label;
    }
    break;
  case wb::ToolbarDropDown:
    {
      Gtk::Alignment *align= new Gtk::Alignment(0.5, 0.5, 0.0, 0.0);
      std::vector<std::string> items;
      std::string selected;
      Gtk::ComboBox *combo;

      items= _be->get_dropdown_items(item.name, item.command, selected);

      if (items.size() > 0 && items[0][0] == '#')
      {
        combo= create_color_combo(items, selected);
        combo->signal_changed().connect(sigc::bind(sigc::mem_fun(this, &ToolbarManager::color_combo_changed),
                                                item.name, combo));

      }
      else
      {
        int i= 0, index= 0;
        combo= new Gtk::ComboBoxText();

        for (std::vector<std::string>::const_iterator iter= items.begin();
             iter != items.end(); ++iter, ++i)
        {
          ((Gtk::ComboBoxText*)combo)->append_text(*iter);
          if (*iter == selected)
            index= i;
         
          combo->signal_changed().connect(sigc::bind(sigc::mem_fun(this, &ToolbarManager::combo_changed),
                                                     item.name, (Gtk::ComboBoxText*)combo));

        }
        
        combo->set_active(index);
      }
      combo->set_name(item.command);
      align->add(*Gtk::manage(combo));

      combo->show();

      w= align;
    }
    break;
    
  case wb::ToolbarSearch:
    {
      _search_conn.disconnect();
      
      Gtk::HBox *hbox= Gtk::manage(new Gtk::HBox(false, 0));
      Gtk::Image *image= Gtk::manage(new Gtk::Image(Gtk::Stock::FIND, Gtk::ICON_SIZE_MENU));
      Gtk::Entry *entry= Gtk::manage(new Gtk::Entry());
      
      hbox->pack_start(*image, false, true);
      hbox->pack_start(*entry, true, true);
      hbox->show_all();
      w= hbox;

      _search_conn = entry->signal_key_release_event().connect(sigc::bind(sigc::mem_fun(this, &ToolbarManager::on_searchitem_key_release_event), entry));
    }
    break;
  }

  if (w)
  {
    w->set_sensitive(item.enabled);
    
    w->show();
    if (right)
      toolbar->pack_end(*Gtk::manage(w), false, false);
    else
      toolbar->pack_start(*Gtk::manage(w), false, false);
  }
}

//------------------------------------------------------------------------------
void ToolbarManager::rebuild_toolbar(Gtk::Box *toolbar, const std::string& toolbar_name)
{
  if ( !toolbar_name.empty() && toolbar )
  {
    toolbar->foreach(sigc::mem_fun(*toolbar, &Gtk::Container::remove));

    std::vector<wb::WBToolbarItem> items = _be->get_toolbar_items(toolbar_name);

    std::vector<wb::WBToolbarItem>::const_iterator cur_toolbar_item = items.begin();
    for (; cur_toolbar_item != items.end(); ++cur_toolbar_item)
    {
      if (g_str_has_suffix(cur_toolbar_item->name.c_str(), "right"))
        add_toolbar_item(toolbar, *cur_toolbar_item, true);
      else
        add_toolbar_item(toolbar, *cur_toolbar_item, false);
    }
    
    toolbar->show_all_children();
  }
}

//------------------------------------------------------------------------------
void ToolbarManager::clicked(const Gtk::Button *btn)
{
  _be->activate_command(btn->get_name());
}


void ToolbarManager::toggled(const Gtk::ToggleButton *btn, const std::string &name, const std::string &option)
{
  _be->toggle_checkbox_item(name, option, btn->get_active());
}


void ToolbarManager::combo_changed(const std::string &toolbar, Gtk::ComboBoxText *combo)
{
  if (combo->get_active_row_number() >= 0)
  {  
    _be->select_dropdown_item(toolbar, combo->get_name(), combo->get_active_text());
  }
}


void ToolbarManager::color_combo_changed(const std::string &toolbar, Gtk::ComboBox *combo)
{
  if (combo->get_active_row_number() >= 0)
  { 
    Gtk::TreeRow row= *combo->get_active();
    
    _be->select_dropdown_item(toolbar, combo->get_name(), row[color_combo_columns->color]);
  }
}

bool ToolbarManager::on_searchitem_key_release_event(GdkEventKey* event, Gtk::Entry* e)
{
  if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter)
  {
    _search_text = e->get_text();
    _be->activate_command("builtin:searchbox");
  }
  return false;
}

  

