//////////////////////////////////////////////////////////////////////////////
//
//    DISPLAYCOMPARE.CPP
//
//    Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
//    Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
//
//    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, Cambridge, MA 02110-1301, USA.
//
//////////////////////////////////////////////////////////////////////////////

// Include files for TQt

#include <tqptrvector.h>
#include <tqdict.h>
#include <tqfile.h>
#include <tqlistbox.h>
#include <tqlabel.h>
#include <tqgroupbox.h>
#include <tqlistview.h>
#include <tqcheckbox.h>
#include <tqheader.h>
#include <tqlayout.h>
#include <tqfileinfo.h>
#include <tqimage.h>
#include <tqpixmap.h>
#include <tqwhatsthis.h>
#include <tqpushbutton.h>
#include <tqframe.h>

// Include files for KDE

#include <klocale.h>
#include <kmessagebox.h>
#include <kiconloader.h>
#include <klistview.h>
#include <ksqueezedtextlabel.h>
#include <kapplication.h>
#include <kurl.h>
#include <kio/job.h>
#include <kio/jobclasses.h>
#include <kio/netaccess.h>
#include <kio/global.h>
#include <kimageio.h>
#include <kio/previewjob.h>
#include <khelpmenu.h>
#include <kpopupmenu.h>
#include <kstandarddirs.h>

// Include files for KIPI

#include <libkipi/version.h>

// Local include files

#include "pluginsversion.h"
#include "kpaboutdata.h"
#include "displaycompare.h"

namespace KIPIFindDupplicateImagesPlugin
{

/////////////////////////////////////////////////////////////////////////////////////////////

class FindOriginalItem : public TQCheckListItem
{
public:
    FindOriginalItem(TQListView * parent, TQString const & name, TQString const & fullpath,
                       TQString const & album, TQString const & comments)
                     : TQCheckListItem( parent, name, TQCheckListItem::CheckBox), _name(name),
                       _fullpath(fullpath), _album (album), _comments (comments)
    {}

    TQString name()         { return _name;     }
    TQString fullpath()     { return _fullpath; }
    TQString album()        { return _album;    }
    TQString comments()     { return _comments; }

private:
    TQString _name;
    TQString _fullpath;
    TQString _album;
    TQString _comments;
};


/////////////////////////////////////////////////////////////////////////////////////////////

class FindDuplicateItem : public TQCheckListItem
{
public:
    FindDuplicateItem(TQListView * parent, TQString const & name, TQString const & fullpath,
                       TQString const & album, TQString const & comments)
                     : TQCheckListItem( parent, name, TQCheckListItem::CheckBox), _name(name),
                       _fullpath(fullpath), _album (album), _comments (comments)
    {}

    TQString name()         { return _name;     }
    TQString fullpath()     { return _fullpath; }
    TQString album()        { return _album;    }
    TQString comments()     { return _comments; }

private:
    TQString _name;
    TQString _fullpath;
    TQString _album;
    TQString _comments;
};


//////////////////////////////////// CONSTRUCTOR ////////////////////////////////////////////

DisplayCompare::DisplayCompare(TQWidget* parent, KIPI::Interface* interface,
                               const TQDict < TQPtrVector < TQFile > >& cmp )
              : KDialogBase( parent, "DisplayCompare", true, 0,
                Help|User1|Close, Close, false, i18n("Delete")),
                m_cmp(cmp), m_interface( interface )
{
    KImageIO::registerFormats();

    // About data and help button.

    m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Find Duplicate Images"),
                                           0,
                                           KAboutData::License_GPL,
                                           I18N_NOOP("A Kipi plugin to find duplicate images\n"
                                                     "This plugin is based on ShowImg implementation algorithm"),
                                           "(c) 2003-2004, Gilles Caulier");

    m_about->addAuthor("Jesper K. Pedersen", I18N_NOOP("Maintainer"),
                       "blackie atkde dot org");

    m_about->addAuthor("Gilles Caulier", I18N_NOOP("Original author"),
                       "caulier dot gilles at gmail dot com");

    m_about->addAuthor("Richard Groult", I18N_NOOP("Find duplicate images algorithm"),
                       "rgroult at jalix.org");

    m_helpButton = actionButton( Help );
    KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
    helpMenu->menu()->removeItemAt(0);
    helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, TQT_SLOT(slotHelp()), 0, -1, 0);
    m_helpButton->setPopup( helpMenu->menu() );

    // ----------------------------------------------------

    TQWidget* box = new TQWidget( this );
    setMainWidget(box);
    TQVBoxLayout* ml = new TQVBoxLayout( box, 10 );
    TQHBoxLayout* h1 = new TQHBoxLayout( ml );
    TQVBoxLayout* v1 = new TQVBoxLayout( h1 );
    h1->addSpacing( 5 );
    TQGridLayout* g1 = new TQGridLayout( v1, 1, 2 );

    //---------------------------------------------

    GroupBox1 = new TQGroupBox( 1, Qt::Horizontal, i18n("Original Files"), box );
    GroupBox1->layout()->setSpacing( 6 );
    GroupBox1->layout()->setMargin( 11 );

    OriginalNameLabel = new KSqueezedTextLabel( GroupBox1, "OriginalNameLabel" );
    OriginalNameLabel->setFrameShape( TQLabel::Box );
    OriginalNameLabel->setAlignment( int( TQLabel::AlignCenter ) );

    preview1 = new TQLabel( GroupBox1, "preview1" );
    preview1->setFixedHeight( 120 );
    preview1->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter );
    preview1->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) );
    TQWhatsThis::add( preview1, i18n( "<p>The preview of files with duplicates." ) );

    originalInfoLabel1 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel1" );
    originalInfoLabel1->setAlignment( int( TQLabel::AlignCenter ) );
    originalInfoLabel2 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel2" );
    originalInfoLabel2->setAlignment( int( TQLabel::AlignCenter ) );
    originalInfoLabel3 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel3" );
    originalInfoLabel3->setAlignment( int( TQLabel::AlignCenter ) );
    originalInfoLabel4 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel4" );
    originalInfoLabel4->setAlignment( int( TQLabel::AlignCenter ) );
    originalInfoLabel5 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel5" );
    originalInfoLabel5->setAlignment( int( TQLabel::AlignCenter ) );

    listName = new KListView( GroupBox1, "listName" );
    listName->header()->setLabel( 0, i18n( "Files" ) );
    TQWhatsThis::add( listName, i18n( "<p>This list contains all files with many duplicates." ) );
    listName->addColumn( i18n( "Files" ) );
    listName->setResizeMode(TQListView::AllColumns);

    g1->addWidget( GroupBox1 , 0, 0);

    //---------------------------------------------

    GroupBox2 = new TQGroupBox( 1, Qt::Horizontal, i18n("Similar Files"), box );
    GroupBox2->layout()->setSpacing( 6 );
    GroupBox2->layout()->setMargin( 11 );

    similarNameLabel = new KSqueezedTextLabel( GroupBox2, "similarNameLabel" );
    similarNameLabel->setFrameShape( TQLabel::Box );
    similarNameLabel->setAlignment( int( TQLabel::AlignCenter ) );

    preview2 = new TQLabel( GroupBox2, "preview2" );
    preview2->setFixedHeight( 120 );
    preview2->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter );
    preview2->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) );
    TQWhatsThis::add( preview2, i18n( "<p>The preview of duplicate files." ) );

    similarInfoLabel1 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel1" );
    similarInfoLabel1->setAlignment( int( TQLabel::AlignCenter ) );
    similarInfoLabel2 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel2" );
    similarInfoLabel2->setAlignment( int( TQLabel::AlignCenter ) );
    similarInfoLabel3 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel3" );
    similarInfoLabel3->setAlignment( int( TQLabel::AlignCenter ) );
    similarInfoLabel4 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel4" );
    similarInfoLabel4->setAlignment( int( TQLabel::AlignCenter ) );
    similarInfoLabel5 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel5" );
    similarInfoLabel5->setAlignment( int( TQLabel::AlignCenter ) );

    listEq = new KListView( GroupBox2, "listEq" );
    listEq->header()->setLabel( 0, i18n( "Files" ) );
    TQWhatsThis::add( listEq, i18n( "<p>This list contains all duplicates files." ) );
    listEq->addColumn( i18n( "Identical To" ) );
    listEq->setResizeMode(TQListView::AllColumns);

    g1->addWidget( GroupBox2 , 0, 1);

    setTabOrder( listName, listEq );

    //---------------------------------------------

    TQDictIterator < TQPtrVector < TQFile > >itres(m_cmp);    // iterator for res
    int n_id = 0;

    while (itres.current ())
        {
        TQFileInfo fi(itres.currentKey());
        TQString Temp = fi.dirPath();
        TQString albumName = Temp.section('/', -1);

        KURL url;
        url.setPath(fi.fileName());
        KIPI::ImageInfo info = m_interface->info(url);
        TQString comments = info.description();

        new FindOriginalItem( listName, fi.fileName(), itres.currentKey(), albumName, comments );
        ++itres;
        ++n_id;
        }

    setCaption(i18n("1 Original Image with Duplicate Images Has Been Found",
                    "%n Original Images with Duplicate Images Have Been Found", n_id));

    // signals and slots connections

    connect(this, TQT_SIGNAL(user1Clicked()),
            this, TQT_SLOT(slotDelete()));

    connect(listName, TQT_SIGNAL(selectionChanged ( TQListViewItem * )),
            this, TQT_SLOT(slotDisplayLeft(TQListViewItem *)));

    connect(listEq, TQT_SIGNAL(selectionChanged ( TQListViewItem * )),
            this, TQT_SLOT(slotDisplayRight(TQListViewItem *)));

    resize( 700, 600 );
    listName->setSelected(listName->firstChild(), true);
}


//////////////////////////////////// DESTRUCTOR /////////////////////////////////////////////

DisplayCompare::~DisplayCompare()
{
    delete m_about;
}


/////////////////////////////////////////////////////////////////////////////////////////////

void DisplayCompare::slotHelp()
{
    KApplication::kApplication()->invokeHelp("findduplicateimages",
                                             "kipi-plugins");
}


/////////////////////////////////////////////////////////////////////////////////////////////

void DisplayCompare::slotDelete( void )
{
    FindDuplicateItem *item = (FindDuplicateItem*)listEq->firstChild ();
    FindDuplicateItem *itemTmp;

    while(item)    // Remove duplicate file selected.
       {
       if( item->isOn() )
           {
           itemTmp = (FindDuplicateItem*)item->nextSibling();
           KURL deleteImage(item->fullpath());

           if ( KIO::NetAccess::del(deleteImage) == false )
              KMessageBox::error(this, i18n("Cannot remove duplicate file:\n%1").arg(item->fullpath()));
           else
              m_interface->delImage( deleteImage );

           listEq->takeItem (item);
           item = itemTmp;
           }
        else
           item = (FindDuplicateItem*)item->nextSibling();
        }

    // Remove originals files selected.

    for (FindOriginalItem* item = (FindOriginalItem*)listName->firstChild(); item;
         item = (FindOriginalItem*)item->nextSibling())
        {
        if ( item->isOn() )
           {
           KURL deleteImage(item->fullpath());

           if ( KIO::NetAccess::del(deleteImage) == false )
              KMessageBox::error(this, i18n("Cannot remove original file:\n%1").arg(item->fullpath()));

           item->setOn( false );
           }
        }
}


/////////////////////////////////////////////////////////////////////////////////////////////

void DisplayCompare::slotDisplayLeft(TQListViewItem * item)
{
    KApplication::setOverrideCursor( waitCursor );
    listEq->clear();
    FindOriginalItem *pitem = static_cast<FindOriginalItem*>( item );
    TQPtrVector < TQFile > *list = (TQPtrVector < TQFile > *)m_cmp.find(pitem->fullpath());
    TQImage im(pitem->fullpath());

    if ( !im.isNull() )
       {
       OriginalNameLabel->setText(pitem->name());
       originalInfoLabel1->setText(i18n("Image size: %1x%2 pixels").arg(im.width()).arg(im.height()));
       originalInfoLabel2->setText(i18n("File size: 1 byte",
                                        "File size: %n bytes",TQFileInfo(pitem->fullpath()).size()));
       originalInfoLabel3->setText(i18n("Modified: %1").arg(KLocale(NULL)
                                   .formatDateTime(TQFileInfo(pitem->fullpath())
                                   .lastModified())));
       originalInfoLabel4->setText(i18n("Album: %1").arg(pitem->album()));
       originalInfoLabel5->setText(i18n("Comments: %1").arg(pitem->comments()));
       }

    preview1->clear();

    TQString IdemIndexed = "file:" + pitem->fullpath();
    KURL url(IdemIndexed);

    KIO::PreviewJob* thumbJob1 = KIO::filePreview( url, preview1->height() );

    connect(thumbJob1, TQT_SIGNAL(gotPreview(const KFileItem*, const TQPixmap&)),
            TQT_SLOT(slotGotPreview1(const KFileItem*, const TQPixmap&)));

    FindDuplicateItem *last = NULL;
    TQFile *f = NULL;
    TQFileInfo *fi = new TQFileInfo();
    TQString fn;

    for (unsigned int i = 0 ; i < list->size () ; ++i)
       {
       f = (TQFile*)list->at(i);
       fi->setFile(*f);
       fn =  fi->absFilePath();

       if (fi->exists ())
          {
          TQString Temp = fi->dirPath();
          TQString albumName = Temp.section('/', -1);

          KURL url;
          url.setPath(fi->fileName());
          KIPI::ImageInfo info = m_interface->info(url);
          TQString comments = info.description();

          FindDuplicateItem *item = new FindDuplicateItem( listEq,
                                                           fi->fileName(),
                                                           fn,
                                                           albumName,
                                                           comments
                                                           );
          if (!last)
             last = item;
          }
       }

    preview2->setPixmap(TQPixmap());
    listEq->setSelected(last, true);
    KApplication::restoreOverrideCursor();
}


/////////////////////////////////////////////////////////////////////////////////////////////

void DisplayCompare::slotGotPreview1(const KFileItem* /*url*/, const TQPixmap &pixmap)
{
    preview1->setPixmap(pixmap);
}


/////////////////////////////////////////////////////////////////////////////////////////////

void DisplayCompare::slotDisplayRight(TQListViewItem * item)
{
    KApplication::setOverrideCursor( waitCursor );
    FindDuplicateItem *pitem = static_cast<FindDuplicateItem*>( item );
    TQImage im(pitem->fullpath());

    if ( !im.isNull() )
       {
       similarNameLabel->setText(pitem->name());
       similarInfoLabel1->setText(i18n("Image size: %1x%2 pixels").arg(im.width()).arg(im.height()));
       similarInfoLabel2->setText(i18n("File size: 1 byte",
                                       "File size: %n bytes", TQFileInfo(pitem->fullpath()).size()));
       similarInfoLabel3->setText(i18n("Modified: %1").arg(KLocale(NULL)
                                                      .formatDateTime(TQFileInfo(pitem->fullpath())
                                                      .lastModified())));
       similarInfoLabel4->setText(i18n("Album: %1").arg(pitem->album()));
       similarInfoLabel5->setText(i18n("Caption: %1").arg(pitem->comments()));
       }

    preview2->clear();

    TQString IdemIndexed = "file:" + pitem->fullpath();
    KURL url(IdemIndexed);

    KIO::PreviewJob* thumbJob2 = KIO::filePreview( url, preview2->height() );

    connect(thumbJob2, TQT_SIGNAL(gotPreview(const KFileItem*, const TQPixmap&)),
            TQT_SLOT(slotGotPreview2(const KFileItem*, const TQPixmap&)));

    KApplication::restoreOverrideCursor();
    }


/////////////////////////////////////////////////////////////////////////////////////////////

void DisplayCompare::slotGotPreview2(const KFileItem* /*url*/, const TQPixmap &pixmap)
{
    preview2->setPixmap(pixmap);
}

}  // NameSpace KIPIFindDupplicateImagesPlugin

#include "displaycompare.moc"
