/***************************************************************************
 *   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 "defaultplugin.h"
#include "metabarwidget.h"

#include <kurl.h>
#include <kstandarddirs.h>
#include <kicontheme.h>
#include <tdehtmlview.h>
#include <tdelocale.h>
#include <tdeapplication.h>
#include <kdesktopfile.h>
#include <ktrader.h>
#include <krun.h>
#include <tdefilemetainfo.h>
#include <tdeconfig.h>
#include <kimageio.h>
#include <kdebug.h>
#include <kmdcodec.h>

#include <tdeio/previewjob.h>

#include <dcopclient.h>
#include <dcopref.h>

#include <tqdir.h>
#include <tqfile.h>
#include <tqrect.h>
#include <tqpoint.h>
#include <tqbuffer.h>

#include <dom_string.h>
#include <html_image.h>

#define EVENT_TYPE DOM::DOMString("click")
#define MODIFICATION 1

DefaultPlugin::DefaultPlugin(TDEHTMLPart* html, MetabarFunctions *functions, const char *name) : ProtocolPlugin (html, functions, name)
{
  services = new ServiceLoader(m_html->view(), "serviceloader");
  
  preview_job = 0;
}

DefaultPlugin::~DefaultPlugin()
{
}

void DefaultPlugin::killJobs(){
  if(preview_job){  
    preview_job->kill();
    preview_job = 0;
  }
}

void DefaultPlugin::deactivate()
{  
  m_functions->hide("actions");
  m_functions->hide("open");
  m_functions->hide("info");
  m_functions->hide("preview");
}

void DefaultPlugin::loadActions(DOM::HTMLElement node)
{ 
  KFileItem *item = m_items.getFirst();
  KURL url = item->url();
  
  TDEConfig config("metabarrc", true, false);
  config.setGroup("General");
  
  TDEConfig iconConfig(locate("data", "metabar/iconsrc"));
  iconConfig.setGroup("Icons");
  
  DOM::DOMString innerHTML;
  
  TQStringList actions = config.readListEntry("Actions");
  int maxActions = config.readNumEntry("MaxActions", 5);
  int actionCount = 0;
  
  for(TQStringList::Iterator it = actions.begin(); it != actions.end(); ++it){
    if((*it).startsWith("metabar/")){
      if((*it).right((*it).length() - 8) == "share"){
        MetabarWidget::addEntry(innerHTML, i18n("Share"), "action://" + *it, "network", TQString(), actionCount < maxActions ? TQString() : TQString("hiddenaction"), actionCount >= maxActions);
        actionCount++;
      }
    }
    else{
      DCOPRef action(kapp->dcopClient()->appId(), TQCString(m_html->view()->topLevelWidget()->name()).append("/action/").append((*it).utf8()));

      if(!action.isNull()){
        if(action.call("enabled()")){
          TQString text = action.call("plainText()");
          TQString icon = iconConfig.readEntry(*it, action.call("icon()"));
          
          MetabarWidget::addEntry(innerHTML, text, "action://" + *it, icon, TQString(), actionCount < maxActions ? TQString() : TQString("hiddenaction"), actionCount >= maxActions);
          actionCount++;
        }
      }
    }
  }
  
  config.setGroup("General");
  if(config.readBoolEntry("ShowServicemenus", true)){
    services->loadServices(*(m_items.getFirst()), innerHTML, actionCount);
  }

  if(actionCount == 0) {
    m_functions->hide("actions");
  }
  else{
    if(actionCount > maxActions){
      MetabarWidget::addEntry(innerHTML, i18n("More"), "more://hiddenaction", "1downarrow", "hiddenaction");
    }
    
    node.setInnerHTML(innerHTML);
    m_functions->show("actions");
  }
}

void DefaultPlugin::loadApplications(DOM::HTMLElement node)
{
  if(m_items.count() == 1){
    KFileItem *item = m_items.getFirst();
    KURL url = item->url();
    
    TQDir dir(url.path());
    dir = dir.canonicalPath();
  
    if(item->isDir() || dir.isRoot()){
      m_functions->hide("open");
      node.setInnerHTML(DOM::DOMString());
    }
    else{
      DOM::DOMString innerHTML;
      
      if(KDesktopFile::isDesktopFile(item->url().path())){ //Desktop file
        KDesktopFile desktop(url.path(), true);
        
        if(desktop.hasApplicationType ()){                    
          MetabarWidget::addEntry(innerHTML, i18n("Run %1").arg(desktop.readName()), "desktop://" + url.path(), desktop.readIcon());
          
          m_functions->show("open");
        }
    
        else{
          m_functions->hide("open");
        }
      }
      else{ //other files
        TDETrader::OfferList offers;
        
        offers = TDETrader::self()->query(item->mimetype(), "Type == 'Application'");
        if(!offers.isEmpty()){
          TDEConfig config("metabarrc", true, false);
          config.setGroup("General");
        
          int id = 0;
          int max = config.readNumEntry("MaxEntries", 5);
          
          runMap.clear();      
          TDETrader::OfferList::ConstIterator it = offers.begin();
          
          for(; it != offers.end(); it++){
            TQString nam;
            nam.setNum(id);
            
            bool hide = id >= max;
            MetabarWidget::addEntry(innerHTML, (*it)->name(), "exec://" + nam, (*it)->icon(), TQString(), hide ? TQString("hiddenapp") : TQString(), hide);
            
            runMap.insert(id, *it);
            id++;
          }
          
          if(id > max){
            MetabarWidget::addEntry(innerHTML, i18n("More"), "more://hiddenapp", "1downarrow", "hiddenapp");
          }
        }
        else{
          MetabarWidget::addEntry(innerHTML, i18n("Choose Application"), "openwith:///", "run");
        }
      }
      
      node.setInnerHTML(innerHTML);
      
      m_functions->show("open");
    }
  }
  else{
    m_functions->hide("open");
  }
}

void DefaultPlugin::loadInformation(DOM::HTMLElement node)
{
  if(m_items.count() == 1){
    KFileItem *item = m_items.getFirst();
    KFileItem *that = const_cast<KFileItem *>(item);
    
    DOM::DOMString innerHTML;
    innerHTML += "<ul class=\"info\"><b>" + i18n("Type") + ": </b>";
    innerHTML += that->determineMimeType()->comment();
    innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Size") + ": </b>";
    innerHTML += TDEIO::convertSize(item->size());
    innerHTML += "</ul><ul class=\"info\"><b>" + i18n("User") + ": </b>";
    innerHTML += item->user();
    innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Group") + ": </b>";
    innerHTML += item->group();
    innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Permissions") + ": </b>";
    innerHTML += (item->permissionsString());
    innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Modified") + ": </b>";
    innerHTML += item->timeString(TDEIO::UDS_MODIFICATION_TIME);
    innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Accessed") + ": </b>";
    innerHTML += item->timeString(TDEIO::UDS_ACCESS_TIME);
    innerHTML += "</ul>";
        
    if(item->isLink()){
      innerHTML += "<ul class=\"info\"><b>" + i18n("Linktarget") + ": </b>";
      innerHTML += item->linkDest();
      innerHTML += "</ul>";
    }
        
    if(!item->isDir()){
      const KFileMetaInfo &metaInfo = item->metaInfo();
      if(metaInfo.isValid()){
        TQStringList groups = metaInfo.supportedGroups();
        
        int id = 0;
        TQString nam;
        
        for(TQStringList::ConstIterator it = groups.begin(); it != groups.end(); ++it){
          KFileMetaInfoGroup group = metaInfo.group(*it);
          if(group.isValid()){
            nam.setNum(id);
            
            innerHTML += "<ul class=\"info\"><a class=\"infotitle\" id=\"info_" + nam + "\" href=\"more://info_" + nam + "\">" + group.translatedName() + "</a></ul>";
            
            TQStringList keys = group.supportedKeys();
          
            for(TQStringList::ConstIterator it = keys.begin(); it != keys.end(); ++it){
              const KFileMetaInfoItem metaInfoItem = group.item(*it);
              
              if(metaInfoItem.isValid()){
              
                innerHTML += "<ul class=\"info\" style=\"display:none\"><b name=\"info_" + nam + "\">" + metaInfoItem.translatedKey() + ": </b>";
                innerHTML += metaInfoItem.string();
                innerHTML += "</ul>";
              }
            }
            
            id++;
          }
        }
      }
    }
        
    node.setInnerHTML(innerHTML);
  }
  else{
    TDEIO::filesize_t size = 0;
    int files = 0;
    int dirs  = 0;
    
    for(KFileItemListIterator it(m_items); it.current(); ++it){
      size += (*it)->size();
      
      if((*it)->isDir()){
        dirs++;
      }
      else{
        files++;
      }
    }
 
    DOM::DOMString innerHTML;
    innerHTML += "<ul class=\"info\"><b>" + i18n("Size") + ": </b>";
    innerHTML += TDEIO::convertSize(size);
    innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Files") + ": </b>";
    innerHTML += TQString(TQString().setNum(files));
    innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Folders") + ": </b>";
    innerHTML += TQString(TQString().setNum(dirs));
        innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Total Entries") + ": </b>";
    innerHTML += TQString(TQString().setNum(m_items.count()));
    innerHTML += "</ul>";    
    node.setInnerHTML(innerHTML);
  }
  m_functions->show("info");
}

void DefaultPlugin::loadPreview(DOM::HTMLElement node)
{
  if(m_items.count() == 1){
    KFileItem *item = m_items.getFirst();
    KURL url = item->url();

    TQDir dir(url.path());
    dir = dir.canonicalPath();
    
    if(item->isDir() || dir.isRoot()){
      m_functions->hide("preview");
    }
    else{
      if(item->mimetype().startsWith("audio/")){
        DOM::DOMString innerHTML("<ul><a class=\"previewdesc\" href=\"preview:///\">");
        innerHTML += i18n("Click to start preview");
        innerHTML += "</a></ul>";
        node.setInnerHTML(innerHTML);
        
        //m_functions->show("preview");
      }
      else{
        DOM::DOMString innerHTML("<ul style=\"text-align-center\"><nobr>");
        innerHTML += i18n("Creating preview");
        innerHTML += "</nobr></ul>";
        node.setInnerHTML(innerHTML);
        
        //m_functions->show("preview");
      
        preview_job = TDEIO::filePreview(KURL::List(url), m_html->view()->width() - 30);
          
        connect(preview_job, TQ_SIGNAL(gotPreview(const KFileItem*, const TQPixmap&)), this, TQ_SLOT(slotSetPreview(const KFileItem*, const TQPixmap&)));
        connect(preview_job, TQ_SIGNAL(failed(const KFileItem *)), this, TQ_SLOT(slotPreviewFailed(const KFileItem *)));
        connect(preview_job, TQ_SIGNAL(result(TDEIO::Job *)), this, TQ_SLOT(slotJobFinished(TDEIO::Job *)));
      }
      
      m_functions->show("preview");
    }
  }
  else{
    m_functions->hide("preview");
  }
}

void DefaultPlugin::loadBookmarks(DOM::HTMLElement node)
{
  m_functions->hide("bookmarks");
}

void DefaultPlugin::slotSetPreview(const KFileItem *item, const TQPixmap &pix)
{
  DOM::HTMLDocument doc = m_html->htmlDocument();
  DOM::HTMLElement node = doc.getElementById("preview");
  
  TQByteArray data;
  TQBuffer buffer(data);
  buffer.open(IO_WriteOnly);
  pix.save(&buffer, "PNG");
  
  TQString src = TQString::fromLatin1("data:image/png;base64,%1").arg(KCodecs::base64Encode(data).data());  
  bool media = item->mimetype().startsWith("video/");

  DOM::DOMString innerHTML;
  
  innerHTML += TQString("<ul style=\"height: %1px\"><a class=\"preview\"").arg(pix.height() + 15);
  
  if(media){
    innerHTML += " href=\"preview:///\"";
  }
  innerHTML +="><img id=\"previewimage\" src=\"";
  innerHTML += src;
  innerHTML += "\" width=\"";
  innerHTML += TQString(TQString().setNum(pix.width()));
  innerHTML += "\" height=\"";
  innerHTML += TQString(TQString().setNum(pix.height()));
  innerHTML += "\" /></a></ul>";
  
  if(media){
    innerHTML += "<ul><a class=\"previewdesc\" href=\"preview:///\">" + i18n("Click to start preview") + "</a></ul>";
  }
  
  node.setInnerHTML(innerHTML);
  
  //script.append("adjustPreviewSize(" + height_str + ");");
  m_functions->show("preview");
  m_functions->adjustSize("preview");
}

void DefaultPlugin::slotPreviewFailed(const KFileItem *item)
{
  DOM::HTMLDocument doc = m_html->htmlDocument();
  DOM::HTMLElement preview = static_cast<DOM::HTMLElement>(doc.getElementById("preview_image"));
  if(!preview.isNull()){
    preview.setAttribute(DOM::DOMString("src"), DOM::DOMString());
  }
  
  m_functions->hide("preview");
}

void DefaultPlugin::slotJobFinished(TDEIO::Job *job)
{
  if(preview_job && job == preview_job){
    preview_job = 0;
  }
}

bool DefaultPlugin::handleRequest(const KURL &url)
{
  TQString protocol = url.protocol();

  if(protocol == "exec"){
    int id = url.host().toInt();
        
    TQMap<int,KService::Ptr>::Iterator it = runMap.find(id);
    if(it != runMap.end()){
    
      KFileItem *item = m_items.getFirst();
      if(item){
        KRun::run( **it, KURL::List(item->url()));
        return true;
      }
    }
  }
  
  else if(protocol == "service"){
    TQString name = url.url().right(url.url().length() - 10);
    
    services->runAction(name);
    return true;
  }
  
  else if(protocol == "servicepopup"){
    TQString id = url.host();
    
    DOM::HTMLDocument doc = m_html->htmlDocument();
    DOM::HTMLElement node = static_cast<DOM::HTMLElement>(doc.getElementById("popup" + id));

    if(!node.isNull()){
      TQRect rect = node.getRect();
      TQPoint p = m_html->view()->mapToGlobal(rect.bottomLeft());
      
      services->showPopup(id, p);
    }
    
    return true;
  }
  
  return false;
}

#include "defaultplugin.moc"
