/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2005-05-21
 * Description : Searches folder view
 *
 * Copyright (C) 2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
 * Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
 * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmx dot 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, 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.
 *
 * ============================================================ */

// TQt includes.

#include <tqfont.h>
#include <tqpainter.h>
#include <tqstyle.h>
#include <tqcursor.h>

// KDE includes.

#include <tdepopupmenu.h>
#include <tdelocale.h>
#include <tdeglobal.h>
#include <kiconloader.h>
#include <tdeversion.h>
#include <tdemessagebox.h>
#include <kinputdialog.h>

// Local includes.

#include "album.h"
#include "albummanager.h"
#include "albumsettings.h"
#include "searchquickdialog.h"
#include "searchadvanceddialog.h"
#include "folderitem.h"
#include "searchfolderview.h"
#include "searchfolderview.moc"

namespace Digikam
{

class SearchFolderItem : public FolderItem
{

public:

    SearchFolderItem(TQListView* parent, SAlbum* album)
        : FolderItem(parent, album->title()),
          m_album(album)
    {
        m_album->setExtraData(parent, this);
    }

    ~SearchFolderItem()
    {
        m_album->removeExtraData(listView());
    }

    int compare(TQListViewItem* i, int , bool ) const
    {
        if (!i)
            return 0;

        if (text(0) == i18n("Last Search"))
            return -1;

        return text(0).localeAwareCompare(i->text(0));
    }

    int id() const
    {
        return m_album ? m_album->id() : 0;
    }

    SAlbum* album() const
    {
        return m_album;
    }

private:

    SAlbum *m_album;
};

SearchFolderView::SearchFolderView(TQWidget* parent)
                : FolderView(parent, "SearchFolderView")
{
    addColumn(i18n("My Searches"));
    setResizeMode(TQListView::LastColumn);
    setRootIsDecorated(false);

    m_lastAddedItem = 0;

    connect(AlbumManager::instance(), TQ_SIGNAL(signalAlbumAdded(Album*)),
            this, TQ_SLOT(slotAlbumAdded(Album*)));

    connect(AlbumManager::instance(), TQ_SIGNAL(signalAlbumDeleted(Album*)),
            this, TQ_SLOT(slotAlbumDeleted(Album*)));

    connect(AlbumManager::instance(), TQ_SIGNAL(signalAlbumsCleared()),
            this, TQ_SLOT(clear()));

    connect(this, TQ_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
            this, TQ_SLOT(slotContextMenu(TQListViewItem*, const TQPoint&, int)));

    connect(this, TQ_SIGNAL(doubleClicked(TQListViewItem*, const TQPoint&, int)),
            this, TQ_SLOT(slotDoubleClicked(TQListViewItem*, const TQPoint&, int)));

    connect(this, TQ_SIGNAL(selectionChanged()),
            this, TQ_SLOT(slotSelectionChanged()));
}

SearchFolderView::~SearchFolderView()
{
    saveViewState();
}

void SearchFolderView::slotTextSearchFilterChanged(const TQString& filter)
{
    TQString search = filter.lower();

    bool atleastOneMatch = false;

    AlbumList sList = AlbumManager::instance()->allSAlbums();
    for (AlbumList::iterator it = sList.begin(); it != sList.end(); ++it)
    {
        SAlbum* salbum             = (SAlbum*)(*it);
        SearchFolderItem* viewItem = (SearchFolderItem*) salbum->extraData(this);

        // Check if a special url query exist to identify a SAlbum dedicaced to Date Search
        // used with TimeLine.
        KURL url     = salbum->kurl();
        TQString type = url.queryItem("type");

        if (salbum->title().lower().contains(search) &&
            type != TQString("datesearch"))
        {
            atleastOneMatch = true;

            if (viewItem)
                viewItem->setVisible(true);
        }
        else
        {
            if (viewItem)
            {
                viewItem->setVisible(false);
            }
        }
    }

    emit signalTextSearchFilterMatch(atleastOneMatch);
}

void SearchFolderView::quickSearchNew()
{
    KURL url;
    SearchQuickDialog dlg(this, url);

    if (dlg.exec() != KDialogBase::Accepted)
        return;

    // Check if there is not already an album with that namespace
    // and return if user aborts the dialog.
    if ( ! checkName( url ) )
        return;

    SAlbum* album = AlbumManager::instance()->createSAlbum(url, true);

    if (album)
    {
        SearchFolderItem* searchItem = (SearchFolderItem*)(album->extraData(this));
        if (searchItem)
        {
            clearSelection();
            setSelected(searchItem, true);
            slotSelectionChanged();
        }
    }
}

void SearchFolderView::extendedSearchNew()
{
    KURL url;
    SearchAdvancedDialog dlg(this, url);

    if (dlg.exec() != KDialogBase::Accepted)
        return;

    // Check if there is not already an album with that name
    // and return if user aborts the dialog.
    if ( ! checkName( url ) )
        return;

    SAlbum* album = AlbumManager::instance()->createSAlbum(url, false);

    if (album)
    {
        SearchFolderItem* searchItem = (SearchFolderItem*)(album->extraData(this));
        if (searchItem)
        {
            clearSelection();
            setSelected(searchItem, true);
            slotSelectionChanged();
        }
    }
}

bool SearchFolderView::checkName( KURL& url )
{
    TQString albumTitle     = url.queryItem("name");
    AlbumManager* aManager = AlbumManager::instance();
    AlbumList aList        = aManager->allSAlbums();
    bool checked           = checkAlbum( albumTitle );

    while ( !checked)
    {
        TQString label = i18n( "Search name already exists."
                              "\nPlease enter a new name:" );
        bool ok;
        TQString newTitle = KInputDialog::getText( i18n("Name exists"), label,
                                                  albumTitle, &ok, this );
        if (!ok)
            return false;

        albumTitle=newTitle;
        checked = checkAlbum( albumTitle );
    }

    url.removeQueryItem( "name" );
    url.addQueryItem( "name", albumTitle );
    return true;
}

bool SearchFolderView::checkAlbum( const TQString& name ) const
{

    AlbumManager* aManager = AlbumManager::instance();
    AlbumList aList        = aManager->allSAlbums();

    for ( AlbumList::Iterator it = aList.begin();
          it != aList.end(); ++it )
    {
        SAlbum *album = (SAlbum*)(*it);
        if ( album->title() == name )
            return false;
    }
    return true;
}

void SearchFolderView::quickSearchEdit(SAlbum* album)
{
    if (!album)
        return;

    KURL url = album->kurl();
    SearchQuickDialog dlg(this, url);

    if (dlg.exec() != KDialogBase::Accepted)
        return;

    AlbumManager::instance()->updateSAlbum(album, url);

    ((SearchFolderItem*)album->extraData(this))->setText(0, album->title());

    clearSelection();
    setSelected((SearchFolderItem*)(album->extraData(this)), true);
}

void SearchFolderView::extendedSearchEdit(SAlbum* album)
{
    if (!album)
        return;

    KURL url = album->kurl();
    SearchAdvancedDialog dlg(this, url);

    if (dlg.exec() != KDialogBase::Accepted)
        return;

    AlbumManager::instance()->updateSAlbum(album, url);

    ((SearchFolderItem*)album->extraData(this))->setText(0, album->title());

    clearSelection();
    setSelected((SearchFolderItem*)(album->extraData(this)), true);
}

void SearchFolderView::searchDelete(SAlbum* album)
{
    if (!album)
        return;

    // Make sure that a complicated search is not deleted accidentally
    int result = KMessageBox::warningYesNo(this, i18n("Are you sure you want to "
                                                      "delete the selected search "
                                                      "\"%1\"?")
                                           .arg(album->title()),
                                           i18n("Delete Search?"),
                                           i18n("Delete"),
                                           KStdGuiItem::cancel());

    if (result != KMessageBox::Yes)
        return;

    AlbumManager::instance()->deleteSAlbum(album);
}

void SearchFolderView::slotAlbumAdded(Album* a)
{
    if (!a || a->type() != Album::SEARCH)
        return;

    SAlbum* album = (SAlbum*)a;

    // Check if a special url query exist to identify a SAlbum dedicaced to Date Search
    // used with TimeLine. In this case, SAlbum is not displayed here, but in TimeLineFolderView.
    KURL url     = album->kurl();
    TQString type = url.queryItem("type");
    if (type == TQString("datesearch")) return;

    SearchFolderItem* item = new SearchFolderItem(this, album);
    item->setPixmap(0, SmallIcon("edit-find", AlbumSettings::instance()->getDefaultTreeIconSize()));
    m_lastAddedItem = item;
}

void SearchFolderView::slotAlbumDeleted(Album* a)
{
    if (!a || a->type() != Album::SEARCH)
        return;

    SAlbum* album = (SAlbum*)a;

    SearchFolderItem* item = (SearchFolderItem*) album->extraData(this);
    if (item)
        delete item;
}

void SearchFolderView::slotSelectionChanged()
{
    if (!active())
        return;

    TQListViewItem* selItem = 0;

    TQListViewItemIterator it( this );
    while (it.current())
    {
        if (it.current()->isSelected())
        {
            selItem = it.current();
            break;
        }
        ++it;
    }

    if (!selItem)
    {
        AlbumManager::instance()->setCurrentAlbum(0);
        return;
    }

    SearchFolderItem* searchItem = dynamic_cast<SearchFolderItem*>(selItem);

    if (!searchItem || !searchItem->album())
        AlbumManager::instance()->setCurrentAlbum(0);
    else
        AlbumManager::instance()->setCurrentAlbum(searchItem->album());
}

void SearchFolderView::slotContextMenu(TQListViewItem* item, const TQPoint&, int)
{
    if (!item)
    {
        TDEPopupMenu popmenu(this);
        popmenu.insertTitle(SmallIcon("digikam"), i18n("My Searches"));
        popmenu.insertItem(SmallIcon("filefind"), i18n("New Simple Search..."), 10);
        popmenu.insertItem(SmallIcon("edit-find"),     i18n("New Advanced Search..."), 11);

        switch (popmenu.exec(TQCursor::pos()))
        {
            case 10:
            {
                quickSearchNew();
                break;
            }
            case 11:
            {
                extendedSearchNew();
                break;
            }
            default:
                break;
        }
    }
    else
    {
        SearchFolderItem* sItem = dynamic_cast<SearchFolderItem*>(item);

        TDEPopupMenu popmenu(this);
        popmenu.insertTitle(SmallIcon("digikam"), i18n("My Searches"));
        popmenu.insertItem(SmallIcon("filefind"), i18n("Edit Search..."), 10);

        if ( sItem->album()->isSimple() )
            popmenu.insertItem(SmallIcon("edit-find"), i18n("Edit as Advanced Search..."), 11);

        popmenu.insertSeparator(-1);
        popmenu.insertItem(SmallIcon("edit-delete"), i18n("Delete Search"), 12);

        switch (popmenu.exec(TQCursor::pos()))
        {
            case 10:
            {
                if (sItem->album()->isSimple())
                    quickSearchEdit(sItem->album());
                else
                    extendedSearchEdit(sItem->album());
                break;
            }
            case 11:
            {
                extendedSearchEdit(sItem->album());
                break;
            }
            case 12:
            {
                searchDelete(sItem->album());
                break;
            }
            default:
                break;
        }
    }
}

void SearchFolderView::slotDoubleClicked(TQListViewItem* item, const TQPoint&, int)
{
    if (!item)
        return;

    SearchFolderItem* sItem = dynamic_cast<SearchFolderItem*>(item);

    if (sItem->album()->isSimple())
        quickSearchEdit(sItem->album());
    else
        extendedSearchEdit(sItem->album());
}

void SearchFolderView::selectItem(int id)
{
    SAlbum *album = AlbumManager::instance()->findSAlbum(id);
    if(!album)
        return;

    SearchFolderItem *item = (SearchFolderItem*)album->extraData(this);
    if(item)
    {
        setSelected(item, true);
        ensureItemVisible(item);
    }
}

}  // namespace Digikam
