/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2004-11-17
 * Description : image properties side bar using data from 
 *               digiKam database.
 *
 * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
 * Copyright (C) 2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
 *
 * 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 <tqrect.h>
#include <tqcolor.h>
#include <tqsplitter.h>

// KDE includes.

#include <tdelocale.h>
#include <tdeconfig.h>
#include <tdeapplication.h>
#include <kcursor.h>
#include <tdeglobal.h>
#include <kiconloader.h>

// Local includes.

#include "ddebug.h"
#include "dimg.h"
#include "imageinfo.h"
#include "imagedescedittab.h"
#include "imageattributeswatch.h"
#include "imagepropertiestab.h"
#include "imagepropertiesmetadatatab.h"
#include "imagepropertiescolorstab.h"
#include "imagepropertiessidebardb.h"
#include "imagepropertiessidebardb.moc"

namespace Digikam
{

class ImagePropertiesSideBarDBPriv
{
public:

    ImagePropertiesSideBarDBPriv()
    {
        desceditTab           = 0;
        dirtyDesceditTab      = false;
        hasPrevious           = false;
        hasNext               = false;
        hasImageInfoOwnership = false;
    }

    bool                 dirtyDesceditTab;

    TQPtrList<ImageInfo>  currentInfos;

    ImageDescEditTab    *desceditTab;

    bool                 hasPrevious;
    bool                 hasNext;

    bool                 hasImageInfoOwnership;
};

ImagePropertiesSideBarDB::ImagePropertiesSideBarDB(TQWidget *parent, const char *name, TQSplitter *splitter, 
                                                   Side side, bool mimimizedDefault)
                        : ImagePropertiesSideBar(parent, name, splitter, side, mimimizedDefault, false)
{
    // Navigate bar is disabled by passing false to parent class constructor, and tab constructors

    d = new ImagePropertiesSideBarDBPriv;
    d->desceditTab = new ImageDescEditTab(parent, false);

    appendTab(d->desceditTab, SmallIcon("imagecomment"), i18n("Captions/Tags"));

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

    connect(this, TQ_SIGNAL(signalChangedTab(TQWidget*)),
            this, TQ_SLOT(slotChangedTab(TQWidget*)));

    connect(d->desceditTab, TQ_SIGNAL(signalProgressBarMode(int, const TQString&)),
            this, TQ_SIGNAL(signalProgressBarMode(int, const TQString&)));

    connect(d->desceditTab, TQ_SIGNAL(signalProgressValue(int)),
            this, TQ_SIGNAL(signalProgressValue(int)));

    ImageAttributesWatch *watch = ImageAttributesWatch::instance();

    connect(watch, TQ_SIGNAL(signalFileMetadataChanged(const KURL &)),
            this, TQ_SLOT(slotFileMetadataChanged(const KURL &)));
}

ImagePropertiesSideBarDB::~ImagePropertiesSideBarDB()
{
    delete d;
}

void ImagePropertiesSideBarDB::itemChanged(ImageInfo *info,
                                           const TQRect &rect, DImg *img)
{
    itemChanged(info->kurl(), info, rect, img);
}

void ImagePropertiesSideBarDB::itemChanged(const KURL& url, const TQRect &rect, DImg *img)
{
    itemChanged(url, 0, rect, img);
}

void ImagePropertiesSideBarDB::itemChanged(const KURL& url, ImageInfo *info,
                                           const TQRect &rect, DImg *img)
{
    if ( !url.isValid() )
        return;

    m_currentURL         = url;

    TQPtrList<ImageInfo> list;
    if (info)
        list.append(info);

    itemChanged(list, rect, img);
}

void ImagePropertiesSideBarDB::itemChanged(TQPtrList<ImageInfo> infos)
{
    if (infos.isEmpty())
        return;

    m_currentURL         = infos.first()->kurl();

    itemChanged(infos, TQRect(), 0);
}

void ImagePropertiesSideBarDB::itemChanged(TQPtrList<ImageInfo> infos,
                                           const TQRect &rect, DImg *img)
{
    m_currentRect        = rect;
    m_image              = img;

    // The list _may_ have autoDelete set to true.
    // Keep old ImageInfo objects from being deleted
    // until the tab has had the chance to save changes and clear lists.
    TQPtrList<ImageInfo> temporaryList;
    if (d->hasImageInfoOwnership)
    {
        temporaryList = d->currentInfos;
        d->hasImageInfoOwnership = false;
    }

    d->currentInfos      = infos;

    m_dirtyPropertiesTab = false;
    m_dirtyMetadataTab   = false;
    m_dirtyColorTab      = false;
    d->dirtyDesceditTab  = false;

    // All tabs that store the ImageInfo list and access it after selection change
    // must release the image info here. slotChangedTab only handles the active tab!
    d->desceditTab->setItem();

    slotChangedTab( getActiveTab() );

    // now delete old objects, after slotChangedTab
    for (ImageInfo *info = temporaryList.first(); info; info = temporaryList.next())
    {
        delete info;
    }
}

void ImagePropertiesSideBarDB::takeImageInfoOwnership(bool takeOwnership)
{
    d->hasImageInfoOwnership = takeOwnership;
}


void ImagePropertiesSideBarDB::slotNoCurrentItem(void)
{
    ImagePropertiesSideBar::slotNoCurrentItem();

    // All tabs that store the ImageInfo list and access it after selection change
    // must release the image info here. slotChangedTab only handles the active tab!
    d->desceditTab->setItem();

    if (d->hasImageInfoOwnership)
    {
        for (ImageInfo *info = d->currentInfos.first(); info; info = d->currentInfos.next())
        {
            delete info;
        }
        d->hasImageInfoOwnership = false;
    }
    d->currentInfos.clear();

    d->desceditTab->setItem();
    d->dirtyDesceditTab = false;
}

void ImagePropertiesSideBarDB::populateTags(void)
{
    d->desceditTab->populateTags();
}

void ImagePropertiesSideBarDB::slotChangedTab(TQWidget* tab)
{
    setCursor(KCursor::waitCursor());

    // No database data available, for example in the case of image editor is 
    // started from camera GUI.
    if (d->currentInfos.isEmpty())
    {
        if (tab == m_propertiesTab && !m_dirtyPropertiesTab)
        {
            m_propertiesTab->setCurrentURL(m_currentURL);
            m_dirtyPropertiesTab = true;
        }
        else if (tab == m_metadataTab && !m_dirtyMetadataTab)
        {
            if (m_image)
                m_metadataTab->setCurrentData(m_image->getExif(), m_image->getIptc(), 
                                              m_currentURL.fileName());
            else
                m_metadataTab->setCurrentURL(m_currentURL);

            m_dirtyMetadataTab = true;
        }
        else if (tab == m_colorTab && !m_dirtyColorTab)
        {
            m_colorTab->setData(m_currentURL, m_currentRect, m_image);
            m_dirtyColorTab = true;
        }
        else if (tab == d->desceditTab && !d->dirtyDesceditTab)
        {
            // Do nothing here. We cannot get data from database !
            d->desceditTab->setItem();
            d->dirtyDesceditTab = true;
        }
    }
    else if (d->currentInfos.count() == 1)   // Data from database available...
    {
        if (tab == m_propertiesTab && !m_dirtyPropertiesTab)
        {
            m_propertiesTab->setCurrentURL(m_currentURL);
            m_dirtyPropertiesTab = true;
        }
        else if (tab == m_metadataTab && !m_dirtyMetadataTab)
        {
            if (m_image)
                m_metadataTab->setCurrentData(m_image->getExif(), m_image->getIptc(),
                                              m_currentURL.fileName());
            else
                m_metadataTab->setCurrentURL(m_currentURL);

            m_dirtyMetadataTab = true;
        }
        else if (tab == m_colorTab && !m_dirtyColorTab)
        {
            m_colorTab->setData(m_currentURL, m_currentRect, m_image);
            m_dirtyColorTab = true;
        }
        else if (tab == d->desceditTab && !d->dirtyDesceditTab)
        {
            d->desceditTab->setItem(d->currentInfos.first());
            d->dirtyDesceditTab = true;
        }
    }
    else  // Data from database available, multiple selection
    {
        if (tab == m_propertiesTab && !m_dirtyPropertiesTab)
        {
            //TODO
            m_propertiesTab->setCurrentURL(m_currentURL);
            m_dirtyPropertiesTab = true;
        }
        else if (tab == m_metadataTab && !m_dirtyMetadataTab)
        {
            // any ideas?
            m_metadataTab->setCurrentURL();
            m_dirtyMetadataTab = true;
        }
        else if (tab == m_colorTab && !m_dirtyColorTab)
        {
            // any ideas?
            m_colorTab->setData();
            m_dirtyColorTab = true;
        }
        else if (tab == d->desceditTab && !d->dirtyDesceditTab)
        {
            d->desceditTab->setItems(d->currentInfos);
            d->dirtyDesceditTab = true;
        }
    }

    unsetCursor();
}

void ImagePropertiesSideBarDB::slotFileMetadataChanged(const KURL &url)
{
    if (url == m_currentURL)
    {
        // trigger an update
        m_dirtyMetadataTab = false;

        if (getActiveTab() == m_metadataTab)
        {
            // update now - reuse code form slotChangedTab
            slotChangedTab( getActiveTab() );
        }
    }
}

void ImagePropertiesSideBarDB::slotAssignRating(int rating)
{
    d->desceditTab->assignRating(rating);
}

void ImagePropertiesSideBarDB::slotAssignRatingNoStar()
{
    d->desceditTab->assignRating(0);
}

void ImagePropertiesSideBarDB::slotAssignRatingOneStar()
{
    d->desceditTab->assignRating(1);
}

void ImagePropertiesSideBarDB::slotAssignRatingTwoStar()
{
    d->desceditTab->assignRating(2);
}

void ImagePropertiesSideBarDB::slotAssignRatingThreeStar()
{
    d->desceditTab->assignRating(3);
}

void ImagePropertiesSideBarDB::slotAssignRatingFourStar()
{
    d->desceditTab->assignRating(4);
}

void ImagePropertiesSideBarDB::slotAssignRatingFiveStar()
{
    d->desceditTab->assignRating(5);
}

void ImagePropertiesSideBarDB::refreshTagsView()
{
    d->desceditTab->refreshTagsView();
}

}  // NameSpace Digikam
