/***************************************************************************
 *   Copyright (C) 2005 by Florian Roth   *
 *   florian@synatic.net   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/


#include <tqgroupbox.h>
#include <tqlayout.h>
#include <tqtabwidget.h>
#include <tqlabel.h>
#include <tqlineedit.h>
#include <tqdir.h>
#include <tqfileinfo.h>
#include <tqmap.h>
#include <tqcstring.h>
#include <tqdatastream.h> 

#include <kdebug.h>
#include <tdelocale.h>
#include <kicondialog.h>
#include <tdeapplication.h>
#include <kiconloader.h>
#include <kstandarddirs.h>
#include <tdefiledialog.h>
#include <ktar.h>
#include <karchive.h>
#include <dcopref.h>
#include <dcopclient.h>

#include "configdialog.h"

LinkEntry::LinkEntry(TQString name, TQString url, TQString icon){
  LinkEntry::name = name;
  LinkEntry::url = url;
  LinkEntry::icon = icon;
}

ActionListItem::ActionListItem(TQListBox *listbox, const TQString &action, const TQString &text, const TQPixmap &pixmap) : TQListBoxPixmap(listbox, pixmap)
{
  setAction(action);
  setText(text);
}

ConfigDialog::ConfigDialog(TQWidget *parent, const char *name) : TQDialog(parent, name)
{
  topWidgetName = parent->topLevelWidget()->name();
  config = new TDEConfig("metabarrc");
  iconConfig = new TDEConfig(locate("data", "metabar/iconsrc"));

  setCaption(i18n("Configuration - Metabar"));
  setIcon(SmallIcon("metabar"));

  ok = new KPushButton(KStdGuiItem::ok(), this);
  connect(ok, TQT_SIGNAL(clicked()), this, TQT_SLOT(accept()));
  
  cancel = new KPushButton(KStdGuiItem::cancel(), this);
  connect(cancel, TQT_SIGNAL(clicked()), this, TQT_SLOT(reject()));
  
  TQTabWidget *tab = new TQTabWidget(this);
  
  //general page
  config->setGroup("General");
  TQWidget *general = new TQWidget;
  
  TQGroupBox *entries_group = new TQGroupBox(2, Qt::Horizontal, i18n("Items"), general);
  entries_group->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Preferred);
  
  TQLabel *entries_label = new TQLabel(i18n("Open with:"), entries_group);
  max_entries = new KIntSpinBox(entries_group);
  max_entries->setMinValue(1);
  max_entries->setMaxValue(99);
  max_entries->setLineStep(1);
  max_entries->setValue(config->readNumEntry("MaxEntries", 3));
  entries_label->setBuddy(max_entries);
  
  TQLabel *actions_label = new TQLabel(i18n("Actions:"), entries_group);
  max_actions = new KIntSpinBox(entries_group);
  max_actions->setMinValue(1);
  max_actions->setMaxValue(99);
  max_actions->setLineStep(1);
  max_actions->setValue(config->readNumEntry("MaxActions", 3));
  actions_label->setBuddy(max_actions);
  
  
  TQGroupBox *appearance_group = new TQGroupBox(1, Qt::Horizontal, i18n("Appearance"), general);
  appearance_group->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Preferred);
  
  animate = new TQCheckBox(i18n("Animate resize"), appearance_group);
  animate->setChecked(config->readBoolEntry("AnimateResize", false));
  
  servicemenus = new TQCheckBox(i18n("Show service menus"), appearance_group);
  servicemenus->setChecked(config->readBoolEntry("ShowServicemenus", true));
  
  showframe = new TQCheckBox(i18n("Show frame"), appearance_group);
  showframe->setChecked(config->readBoolEntry("ShowFrame", true));
  
  TQGroupBox *theme_group = new TQGroupBox(2, Qt::Horizontal, i18n("Themes"), general);
  theme_group->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Preferred);
  
  themes = new KComboBox(theme_group);
  themes->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Preferred);
  
  install_theme = new KPushButton(i18n("Install New Theme..."), theme_group);
  install_theme->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Preferred);
  connect(install_theme, TQT_SIGNAL(clicked()), this, TQT_SLOT(installTheme()));
  
  loadThemes();
  
  //link page
  TQWidget *links = new TQWidget;
  
  link_create = new KPushButton(i18n("New..."), links);
  connect(link_create, TQT_SIGNAL(clicked()), this, TQT_SLOT(createLink()));
  
  link_delete = new KPushButton(i18n("Delete"), links);
  connect(link_delete, TQT_SIGNAL(clicked()), this, TQT_SLOT(deleteLink()));
  
  link_edit = new KPushButton(i18n("Edit..."), links);
  connect(link_edit, TQT_SIGNAL(clicked()), this, TQT_SLOT(editLink()));  
  
  link_up = new KPushButton(links);
  link_up->setIconSet(SmallIconSet("go-up"));
  link_up->setEnabled(false);
  connect(link_up, TQT_SIGNAL(clicked()), this, TQT_SLOT(moveLinkUp()));
  
  link_down = new KPushButton(links);
  link_down->setIconSet(SmallIconSet("go-down"));
  link_down->setEnabled(false);
  connect(link_down, TQT_SIGNAL(clicked()), this, TQT_SLOT(moveLinkDown()));
    
  link_list = new TDEListView(links);
  link_list->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding);
  link_list->setSorting(-1);
  link_list->setItemsMovable(TRUE);
  link_list->addColumn(i18n("Name"));
  link_list->addColumn(i18n("Address"));
  connect(link_list, TQT_SIGNAL(doubleClicked(TQListViewItem*)), this, TQT_SLOT(editLink(TQListViewItem*)));
  connect(link_list, TQT_SIGNAL(selectionChanged()), TQT_SLOT(updateArrows()));
  
  TQWidget *actionPage = new TQWidget;
  
  actionSelector = new TDEActionSelector(actionPage);
  loadAvailableActions();  
  
  tab->addTab(general, i18n("General"));
  tab->addTab(actionPage, i18n("Actions"));
  tab->addTab(links, i18n("Links"));
  
  //layout  
  TQGridLayout *general_layout = new TQGridLayout(general, 2, 2, 5, 5);
  general_layout->addWidget(entries_group, 0, 0);
  general_layout->addWidget(appearance_group, 0, 1);
  general_layout->addMultiCellWidget(theme_group, 1, 1, 0, 1);
  general_layout->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Minimum, TQSizePolicy::Expanding), 2, 0);
  //general_layout->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Minimum, TQSizePolicy::Expanding), 0, 2);
  
  TQVBoxLayout *link_button_layout = new TQVBoxLayout(0, 0, 5);
  link_button_layout->addWidget(link_create);
  link_button_layout->addWidget(link_edit);
  link_button_layout->addWidget(link_delete);
  link_button_layout->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Minimum, TQSizePolicy::Expanding));
  link_button_layout->addWidget(link_up);
  link_button_layout->addWidget(link_down);
  
  TQHBoxLayout *link_layout = new TQHBoxLayout(links, 5, 5);
  link_layout->addWidget(link_list);
  link_layout->addLayout(link_button_layout);
  
  TQHBoxLayout *action_layout = new TQHBoxLayout(actionPage, 5, 5);
  action_layout->addWidget(actionSelector);
  
  TQHBoxLayout *bottom_layout = new TQHBoxLayout(0, 5, 5);
  bottom_layout->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
  bottom_layout->addWidget(ok);
  bottom_layout->addWidget(cancel);
  
  TQVBoxLayout *main_layout = new TQVBoxLayout(this, 5, 5);
  main_layout->addWidget(tab);
  main_layout->addLayout(bottom_layout);
  
  //load config
  config->setGroup("General");
  
  TQStringList _links = config->readListEntry("Links");
  
  for(TQStringList::Iterator it = _links.begin(); it != _links.end(); ++it){
    config->setGroup("Link_" + (*it));
    
    TQString icon_str = config->readEntry("Icon", "folder");
    TQPixmap icon(icon_str);
    if(icon.isNull()){
      icon = SmallIcon(icon_str);
    }
    
    TQListViewItem *item = new TQListViewItem(link_list, link_list->lastItem(), config->readEntry("Name"), config->readEntry("URL"));
    item->setPixmap(0, icon);
    
    linkList.insert(item, new LinkEntry(config->readEntry("Name"), config->readEntry("URL"), icon_str));
  }
  
  config->setGroup("General");
  TQStringList actions = config->readListEntry("Actions");
  for(TQStringList::Iterator it = actions.begin(); it != actions.end(); ++it){
    if((*it).startsWith("metabar/")){
      if((*it).right((*it).length() - 8) == "share"){
        TQString text = i18n("Share");
      
        ActionListItem *item = new ActionListItem(actionSelector->selectedListBox(), *it, text, SmallIcon("network"));
        
        TQListBoxItem *avItem = actionSelector->availableListBox()->findItem(text, TQt::ExactMatch);
        if(avItem){
          delete avItem;
        }
      }
    }
    else{  
      DCOPRef action(kapp->dcopClient()->appId(), TQCString(topWidgetName).append("/action/").append((*it).utf8()));
          
      TQString text = action.call("plainText()");
      TQString icon = iconConfig->readEntry(*it, action.call("icon()"));
      
      ActionListItem *item = new ActionListItem(actionSelector->selectedListBox(), TQString(*it), text, SmallIcon(icon));
      
      TQListBoxItem *avItem = actionSelector->availableListBox()->findItem(text, TQt::ExactMatch);
      if(avItem){
        delete avItem;
      }
    }
  }
  
  resize(400, 300);
}

ConfigDialog::~ConfigDialog()
{
  delete config;
  delete iconConfig;
}

void ConfigDialog::accept()
{
  TQStringList groups = config->groupList();
  for(TQStringList::Iterator it = groups.begin(); it != groups.end(); ++it){
    if((*it).startsWith("Link_")){
      config->deleteGroup(*it);
    }
  }
  
  TQStringList links;
  TQPtrDictIterator<LinkEntry> it(linkList);
  
  TQListViewItem *item = link_list->firstChild();
  while(item) {
    LinkEntry *entry = linkList[item];
    config->setGroup("Link_" + entry->name);
    config->writeEntry("Name", entry->name);
    config->writeEntry("URL", entry->url);
    config->writeEntry("Icon", entry->icon);
    
    links.append(entry->name);
  
    item = item->nextSibling();
  }
  
  TQStringList actions;
  TQListBox *box = actionSelector->selectedListBox();
  
  for(int i = 0; i < box->numRows(); i++){
    ActionListItem *item = static_cast<ActionListItem*>(box->item(i));
    if(item){
      actions.append(item->action());
    }
  }
  
  config->setGroup("General");
  config->writeEntry("Links", links);  
  config->writeEntry("Actions", actions);
  config->writeEntry("Theme", themes->currentText());
  
  config->writeEntry("MaxEntries", max_entries->value());
  config->writeEntry("MaxActions", max_actions->value());
  
  config->writeEntry("AnimateResize", animate->isChecked());
  config->writeEntry("ShowServicemenus", servicemenus->isChecked());
  config->writeEntry("ShowFrame", showframe->isChecked());
  
  config->sync();
  
  TQDialog::accept();
}

void ConfigDialog::createLink()
{
  TQDialog *main = new TQDialog(this);
  main->setCaption(i18n("Create Link"));
  main->setIcon(SmallIcon("metabar"));
  
  KPushButton *ok = new KPushButton(KStdGuiItem::ok(), main);
  connect(ok, TQT_SIGNAL(clicked()), main, TQT_SLOT(accept()));
  
  KPushButton *cancel = new KPushButton(KStdGuiItem::cancel(), main);
  connect(cancel, TQT_SIGNAL(clicked()), main, TQT_SLOT(reject()));
  
  TQLineEdit *name = new TQLineEdit(i18n("New link"), main);
  TQLineEdit *url = new TQLineEdit("file:/", main);
  
  TDEIconButton *icon = new TDEIconButton(main);
  icon->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum);
  icon->setIconType(TDEIcon::Small, TDEIcon::Any);
  icon->setStrictIconSize(true);
  icon->setIcon("folder");
  
  TQHBoxLayout *bottom_layout = new TQHBoxLayout(0, 0, 5);
  bottom_layout->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
  bottom_layout->addWidget(ok);
  bottom_layout->addWidget(cancel);
  
  TQGridLayout *layout = new TQGridLayout(0, 2, 3, 0, 5);
  layout->addMultiCellWidget(icon, 0, 1, 0, 0);
  layout->addWidget(new TQLabel(i18n("Name:"), main), 0, 1);
  layout->addWidget(name, 0, 2);
  layout->addWidget(new TQLabel(i18n("URL:"), main), 1, 1);
  layout->addWidget(url, 1, 2);

  TQVBoxLayout *main_layout = new TQVBoxLayout(main, 5, 5);
  main_layout->addLayout(layout);
  main_layout->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Minimum, TQSizePolicy::Expanding));
  main_layout->addLayout(bottom_layout);
  
  main->resize(300, main->sizeHint().height());
  
  if(main->exec() == TQDialog::Accepted){
    TQString name_str = name->text();
    TQString url_str = url->text();
    TQString icon_str = icon->icon();
    
    if(!name_str.isEmpty() && !url_str.isEmpty()){
      if(icon_str.isEmpty()){
        icon_str = kapp->iconLoader()->iconPath("folder", TDEIcon::Small);
      }
      
      TQPixmap icon(icon_str);
      if(icon.isNull()){
        icon = SmallIcon(icon_str);
      }
      
      TQListViewItem *item = new TQListViewItem(link_list, link_list->lastItem(), name_str, url_str);
      item->setPixmap(0, icon);
      
      linkList.insert(item, new LinkEntry(name_str, url_str, icon_str));
      updateArrows();
    }
  }
  
  delete main;
}

void ConfigDialog::deleteLink()
{
  TQListViewItem *item = link_list->selectedItem();
  if(item){
    linkList.remove(item);
    delete item;
    updateArrows();
  }
}

void ConfigDialog::editLink()
{
  TQListViewItem *item = link_list->selectedItem();
  editLink(item);
}

void ConfigDialog::editLink(TQListViewItem *item)
{
  if(item){  
    TQDialog *main = new TQDialog(this);
    main->setCaption(i18n("Edit Link"));
    main->setIcon(SmallIcon("metabar"));
    
    KPushButton *ok = new KPushButton(KStdGuiItem::ok(), main);
    connect(ok, TQT_SIGNAL(clicked()), main, TQT_SLOT(accept()));
    
    KPushButton *cancel = new KPushButton(KStdGuiItem::cancel(), main);
    connect(cancel, TQT_SIGNAL(clicked()), main, TQT_SLOT(reject()));
    
    TQLineEdit *name = new TQLineEdit(linkList[item]->name, main);
    TQLineEdit *url = new TQLineEdit(linkList[item]->url, main);
    
    TDEIconButton *icon = new TDEIconButton(main);
    icon->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum);
    icon->setIconType(TDEIcon::Small, TDEIcon::Any);
    icon->setStrictIconSize(true);
    icon->setIcon(linkList[item]->icon);
    
    TQHBoxLayout *bottom_layout = new TQHBoxLayout(0, 0, 5);
    bottom_layout->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Expanding, TQSizePolicy::Minimum));
    bottom_layout->addWidget(ok);
    bottom_layout->addWidget(cancel);
    
    TQGridLayout *layout = new TQGridLayout(0, 2, 3, 0, 5);
    layout->addMultiCellWidget(icon, 0, 1, 0, 0);
    layout->addWidget(new TQLabel(i18n("Name:"), main), 0, 1);
    layout->addWidget(name, 0, 2);
    layout->addWidget(new TQLabel(i18n("URL:"), main), 1, 1);
    layout->addWidget(url, 1, 2);
    
    TQVBoxLayout *main_layout = new TQVBoxLayout(main, 5, 5);
    main_layout->addLayout(layout);
    main_layout->addItem(new TQSpacerItem(10, 10, TQSizePolicy::Minimum, TQSizePolicy::Expanding));
    main_layout->addLayout(bottom_layout);
    
    main->resize(300, main->sizeHint().height());
    
    if(main->exec() == TQDialog::Accepted){
      TQString name_str = name->text();
      TQString url_str = url->text();
      TQString icon_str = icon->icon();
      
      if(!name_str.isEmpty() && !url_str.isEmpty()){
        if(icon_str.isEmpty()){
          icon_str = kapp->iconLoader()->iconPath("folder", TDEIcon::Small);
        }
        
        TQPixmap icon(icon_str);
        if(icon.isNull()){
          icon = SmallIcon(icon_str);
        }
        
        linkList[item]->name = name_str;
        linkList[item]->url = url_str;
        linkList[item]->icon = icon_str;
        
        item->setText(0, name_str);
        item->setText(1, url_str);
        item->setPixmap(0, icon);
      }
    }
    
    delete main;
  }
}

void ConfigDialog::moveLinkUp()
{
  TQListViewItem *item = link_list->selectedItem();
  if(item){
    if(link_list->itemIndex(item) > 0){
      
      TQListViewItem *after;
      TQListViewItem *above = item->itemAbove();
      if(above){
        after = above->itemAbove();
      }
      
      TQString name = linkList[item]->name;
      TQString url = linkList[item]->url;
      TQString icon_str = linkList[item]->icon;
      
      TQPixmap icon(icon_str);
      if(icon.isNull()){
        icon = SmallIcon(icon_str);
      }
      
      delete linkList[item];
      linkList.remove(item);
      delete item;
      
      TQListViewItem *newItem = new TQListViewItem(link_list, after, name, url);
      newItem->setPixmap(0, icon);
      link_list->setSelected(newItem, TRUE);
      
      linkList.insert(newItem, new LinkEntry(name, url, icon_str));
      updateArrows();
    }
  }
}

void ConfigDialog::moveLinkDown()
{
  TQListViewItem *item = link_list->selectedItem();
  if(item){
    if(link_list->itemIndex(item) < linkList.count() - 1){
      
      TQListViewItem *after = item->itemBelow();
      
      TQString name = linkList[item]->name;
      TQString url = linkList[item]->url;
      TQString icon_str = linkList[item]->icon;
      
      TQPixmap icon(icon_str);
      if(icon.isNull()){
        icon = SmallIcon(icon_str);
      }
      
      delete linkList[item];
      linkList.remove(item);
      delete item;
      
      TQListViewItem *newItem = new TQListViewItem(link_list, after, name, url);
      newItem->setPixmap(0, icon);
      link_list->setSelected(newItem, TRUE);
      
      linkList.insert(newItem, new LinkEntry(name, url, icon_str));
      updateArrows();
    }
  }
}

void ConfigDialog::loadAvailableActions()
{
  TQListBox *box = actionSelector->availableListBox();
  
  TQByteArray data, replyData;
  TQCString replyType;

  if(DCOPClient::mainClient()->call(kapp->dcopClient()->appId(), topWidgetName, "actionMap()", data, replyType, replyData)){
    if(replyType == "TQMap<TQCString,DCOPRef>"){    
      TQMap<TQCString,DCOPRef> actionMap;
      
      TQDataStream reply(replyData, IO_ReadOnly);
      reply >> actionMap;
      
      iconConfig->setGroup("Icons");
      
      TQMap<TQCString,DCOPRef>::Iterator it;
      for(it = actionMap.begin(); it != actionMap.end(); ++it){
        DCOPRef action = it.data();
        
        TQString text = action.call("plainText()");
        TQCString cname = action.call("name()");
        TQString icon = iconConfig->readEntry(TQString(cname), action.call("icon()"));
        
        ActionListItem *item = new ActionListItem(box, TQString(cname), text, SmallIcon(icon));
      }
    }
  }
  
  //metabar's own actions
  ActionListItem *item = new ActionListItem(box, "metabar/share", i18n("Share"), SmallIcon("network"));
}

void ConfigDialog::updateArrows()
{
  link_up->setEnabled( link_list->childCount()>1 && link_list->currentItem()!=link_list->firstChild() );
  link_down->setEnabled( link_list->childCount()>1 && link_list->currentItem()!=link_list->lastItem() );
}

void ConfigDialog::loadThemes()
{
  themes->clear();
  
  TQString theme = config->readEntry("Theme", "default");
  bool foundTheme = false;

  TQStringList dirs = kapp->dirs()->findDirs("data", "metabar/themes");
  for(TQStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it){
    TQStringList theme_list = TQDir(*it).entryList(TQDir::Dirs);
    
    theme_list.remove(".");
    theme_list.remove("..");
    themes->insertStringList(theme_list);
    
    if(theme_list.find(theme) != theme_list.end()){
      foundTheme = true;
    }
  }
  
  if(foundTheme){
    themes->setCurrentText(theme);
  }
  else{ 
    themes->insertItem(theme);
  }
}

void ConfigDialog::installTheme()
{
  TQString file = KFileDialog::getOpenFileName();
  if(file.isNull() && file.isEmpty()) return;
  
  TQString themedir = locateLocal("data", "metabar/themes");  
  if(themedir.isNull()) return;

  KTar archive(file);
  archive.open(IO_ReadOnly);
  kapp->processEvents();

  const KArchiveDirectory* rootDir = archive.directory();
  rootDir->copyTo(themedir);
  
  archive.close();
  loadThemes();
}

#include "configdialog.moc"
