/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2004-06-18
 * Description : database album interface.
 * 
 * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
 * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
 * Copyright (C) 2006-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.
 * 
 * ============================================================ */

/** @file albumdb.h */

#ifndef ALBUMDB_H
#define ALBUMDB_H

// TQt includes.

#include <tqstring.h>
#include <tqvaluelist.h>
#include <tqstringlist.h>
#include <tqdatetime.h>

// KDE includes.

#include <kurl.h>

// Local includes.

#include "albuminfo.h"
#include "digikam_export.h"

namespace Digikam
{

typedef TQValueList<int>     IntList;
typedef TQValueList<TQ_LLONG> LLongList;

class AlbumDBPriv;

/**
 * This class is responsible for the communication
 * with the sqlite database.
 */
class DIGIKAM_EXPORT AlbumDB
{
public:

    /**
     * Constructor
     */
    AlbumDB();

    /**
     * Destructor
     */
    ~AlbumDB();

    /**
     * Check if the database interface is initialized properly.
     * @return true if it's ready to use, else false.
     */
    bool isValid() const;

    /**
     * Makes a connection to the database and makes sure all tables
     * are available.
     * @param path The database to open
     */
    void setDBPath(const TQString& path);

    /**
     * Returns all albums and their attributes in the database
     * @return a list of albums and their attributes
     */
    AlbumInfo::List scanAlbums();

    /**
     * Returns all tags and their attributes in the database
     * @return a list of tags and their attributes
     */
    TagInfo::List scanTags();

    /**
     * Returns all searches from the database
     * @return a list of searches from the database
     */
    SearchInfo::List scanSearches();

    /**
     * Add a new album to the database with the given attributes
     * @param url        url of the album
     * @param caption    the album caption
     * @param date       the date for the album
     * @param collection the album collection
     * @return the id of the album added or -1 if it failed
     */
    int addAlbum(const TQString& url, const TQString& caption,
                 const TQDate& date, const TQString& collection);

    /**
     * Set a new url for the album. This will not affect the url
     * of the subalbums.
     * @param albumID the id of the album
     * @param url     the new url for the album
     */
    void setAlbumURL(int albumID, const TQString& url);

    /**
     * Set a caption for the album.
     * @param albumID the id of the album
     * @param caption the new caption for the album
     */
    void setAlbumCaption(int albumID, const TQString& caption);

    /**
     * Set a collection for the album.
     * @param albumID    the id of the album
     * @param collection the new collection for the album
     */
    void setAlbumCollection(int albumID, const TQString& collection);

    /**
     * Set a date for the album.
     * @param albumID  the id of the album
     * @param date     the date for the album
     */
    void setAlbumDate(int albumID, const TQDate& date);

    /**
     * Set the icon for the album.
     * @param albumID the id of the album
     * @param iconID  the id of the icon file
     */
    void setAlbumIcon(int albumID, TQ_LLONG iconID);

    /**
     * Get the fullpath for the album icon file
     * @param albumID the id of the album
     */
    TQString getAlbumIcon(int albumID);

    /**
     * Deletes an album from the database. This will not delete the
     * subalbums of the album.
     * @param albumID the id of the album
     */
    void deleteAlbum(int albumID);

    /**
     * Adds a new tag to the database with given name, icon and parent id.
     * @param parentTagID the id of the tag which will become the new tags parent
     * @param name        the name of the tag
     * @param iconKDE     the name of the icon file (this is filename which kde
     * iconloader can load up)
     * @param iconID      the id of the icon file
     * Note: if the iconKDE parameter is empty, then the iconID parameter is used
     * @return the id of the tag added or -1 if it failed
     */
    int addTag(int parentTagID, const TQString& name,
               const TQString& iconKDE, TQ_LLONG iconID);

    /**
     * Set a new name for the tag. 
     * @param tagID the id of the tag
     * @param name  the new name for the tag
     */
    void setTagName(int tagID, const TQString& name);

    /**
     * Set the icon for the tag.
     * @param tagID the id of the tag
     * @param iconKDE the filename for the kde icon file
     * @param iconID the id of the icon file
     * Note: Only one of the iconKDE or iconID parameters is used.
     * if the iconKDE parameter is empty, then the iconID parameter is used
     */
    void setTagIcon(int tagID, const TQString& iconKDE, TQ_LLONG iconID);

    /**
     * Get the icon for the tag.
     * @param tagID the id of the tag
     * @return the path for the icon file. this could be either a simple filename
     * which can be loaded by kiconloader or an absolute filepath to the file
     */
    TQString getTagIcon(int tagID);

    /**
     * Set the parent tagid for the tag. This is equivalent to reparenting
     * the tag
     * @param tagID          the id of the tag
     * @param newParentTagID the new parentid for the tag
     */
    void setTagParentID(int tagID, int newParentTagID);

    /**
     * Deletes a tag from the database. This will not delete the
     * subtags of the tag.
     * @param tagID the id of the tag
     */
    void deleteTag(int tagID);

    /**
     * Add a new search to the database with the given attributes
     * @param name       name of the search
     * @param url        url of the search
     * @return the id of the album added or -1 if it failed
     */
    int addSearch(const TQString& name, const KURL& url);

    /**
     * Updates Search with new attributes
     * @param searchID   the id of the search
     * @param name       name of the search
     * @param url        url of the search
     */
    void updateSearch(int searchID, const TQString& name, const KURL& url);

    /**
     * Delete a search from the database.
     * @param searchID the id of the search
     */
    void deleteSearch(int searchID);

    void beginTransaction();
    void commitTransaction();

    /**
     * This adds a keyword-value combination to the database Settings table
     * if the keyword already exists, the value will be replaced with the new
     * value.
     * @param keyword The keyword
     * @param value The value
     */
    void setSetting(const TQString& keyword, const TQString& value);

    /**
     * This function returns the value which is stored in the database
     * (table Settings).
     * @param keyword The keyword for which the value has to be returned.
     * @return The values which belongs to the keyword.
     */
    TQString getSetting(const TQString& keyword);

    /**
     * This is simple function to put a new Item in the database,
     * without checking if it already exists, but since albumID+name
     * has to be unique, it will simply replace the datetime and comment
     * for an already existing item. 
     * @param albumID The albumID where the file is located.
     * @param name The filename
     * @param datetime The datetime to be stored. Should try to let that be
     * the exif-datetime, but if not available the modification date.
     * @param comment The user comment as found in the exif-headers of the 
     * file.
     * @param rating The user rating as found in the iptc-headers of the 
     * file.
     * @param keywords The user keywords as found in the iptc-headers of the 
     * file.
     * @return the id of item added or -1 if it fails
     */
    TQ_LLONG addItem(int albumID, const TQString& name,
                    const TQDateTime& datetime,
                    const TQString& comment,
                    int rating,
                    const TQStringList& keywordsList);

    /**
     * Find the album of an item
     * @param imageID The ID of the item
     * @return The ID of the PAlbum of the item, or -1 if not found
    */
    int getItemAlbum(TQ_LLONG imageID);

    /**
     * Retrieve the name of the item
     * @param imageID The ID of the item
     * @return The name of the item, or a null string if not found
     */
    TQString getItemName(TQ_LLONG imageID);

    /**
     * Update the date of a item to supplied date
     * @param imageID The ID of the item
     * @param datetime The datetime to be stored. Should try to let that be
     * the exif-datetime, but if not available the modification date.
     * @return It will always return true. Maybe that will change.
     */
    bool setItemDate(TQ_LLONG imageID, const TQDateTime& datetime);

    /**
     * Update the date of a item to supplied date
     * @param albumID The albumID where the file is located.
     * @param name The filename
     * @param datetime The datetime to be stored. Should try to let that be
     * the exif-datetime, but if not available the modification date.
     * @return It will always return true. Maybe that will change.
     */
    bool setItemDate(int albumID, const TQString& name,
                     const TQDateTime& datetime);

    /**
     * Set the caption for the item
     * @param imageID the id of the item
     * @param caption the caption for the item
     */
    void setItemCaption(TQ_LLONG imageID, const TQString& caption);

    /**
     * Set the caption for the item
     * @param albumID the albumID of the item
     * @param name    the name of the item
     * @param caption the caption for the item
     */
    void setItemCaption(int albumID, const TQString& name, const TQString& caption);

    /**
     * Add a tag for the item
     * @param imageID the ID of the item
     * @param tagID   the tagID for the tag
     */
    void addItemTag(TQ_LLONG imageID, int tagID);

    /**
     * Add a tag for the item
     * @param albumID the albumID of the item
     * @param name    the name of the item
     * @param tagID   the tagID for the tag
     */
    void addItemTag(int albumID, const TQString& name, int tagID);

    /**
     * Add tags for the item, create tags with the given paths if they do not yet exist
     * @param tagPaths a list of tag paths
     * @param create create new tags if necessary
     * @returns a list of albumIDs of the tags in tagPaths
     */
    IntList getTagsFromTagPaths(const TQStringList &tagPaths, bool create = true);

    /**
     * Get a list of recently assigned tags (only last 6 tags are listed)
     * @return the list of recently assigned tags
     */
    IntList getRecentlyAssignedTags() const;

    /**
     * Get the caption for the item
     * @param imageID the id  of the item
     * @return the caption for the item
     */
    TQString getItemCaption(TQ_LLONG imageID);

    /**
     * Get the caption for the item
     * @param albumID the albumID of the item
     * @param name    the name of the item
     * @return the caption for the item
     */
    TQString getItemCaption(int albumID, const TQString& name);

    /**
     * Get the datetime for the item
     * @param imageID the ID of the item
     * @return the datetime for the item
     */
    TQDateTime getItemDate(TQ_LLONG imageID);

    /**
     * Get the datetime for the item
     * @param albumID the albumID of the item
     * @param name    the name of the item
     * @return the datetime for the item
     */
    TQDateTime getItemDate(int albumID, const TQString& name);

    /**
     * Get the imageId of the item
     * @param albumId the albumID of the item
     * @param name the name of the item
     * @return the ImageId for the item
     */
    TQ_LLONG getImageId(int albumID, const TQString& name);

    /**
     * Get a list of names of all the tags for the item
     * @param imageID the ID of the item
     * @return the list of names of all tags for the item
     */
    TQStringList getItemTagNames(TQ_LLONG imageID);

    /**
     * Get a list of IDs of all the tags for the item
     * @param imageID the ID of the item
     * @return the list of IDs of all tags for the item
     */
    IntList getItemTagIDs(TQ_LLONG imageID);

    /**
     * Given a set of items (identified by their IDs),
     * this will see if any of the items has a tag.
     * @param imageIDList a list of IDs of the items
     * @return true if at least one of the items has a tag
     */
    bool hasTags(const LLongList& imageIDList);

    /**
     * Given a set of items (identified by their IDs),
     * get a list of ID of all common tags
     * @param imageIDList a list of IDs of the items
     * @return the list of common IDs of the given items
     */
    IntList getItemCommonTagIDs(const LLongList& imageIDList);

    /**
     * Remove a specific tag for the item
     * @param imageID the ID of the item
     * @param tagID   the tagID for the tag
     */
    void removeItemTag(TQ_LLONG imageID, int tagID);

    /**
     * Update the rating of a item to supplied value
     * @param imageID The ID of the item
     * @param rating The rating value to be stored.
     */
    void setItemRating(TQ_LLONG imageID, int rating);

    /**
     * Get the item rating
     * @param imageID the ID of the item
     * @return the rating for the item
     */
    int getItemRating(TQ_LLONG imageID);

    /**
     * Remove all tags for the item
     * @param imageID the ID of the item
     */
    void removeItemAllTags(TQ_LLONG imageID);

    /**
     * Deletes an item from the database.
     * @param albumID The id of the album.
     * @param file The filename of the file to delete.
     */
    void deleteItem(int albumID, const TQString& file);

    /**
     * This can be used to find out the albumID for a given
     * folder. If it does not exist, it will be created and the
     * new albumID will be returned.
     * @param folder The folder for which you want the albumID
     * @return It returns the albumID for that folder.
     */
    int  getOrCreateAlbumId(const TQString& folder);

    /**
     * Returns all items for a given albumid. This is used to
     * verify if all items on disk are consistent with the database
     * in the scanlib class.
     * @param albumID The albumID for which you want all items.
     * @param recursive perform a recursive folder hierarchy parsing
     * @return It returns a TQStringList with the filenames.
     */
    TQStringList getItemNamesInAlbum(int albumID, bool recurssive=false);

    /**
     * Given a albumID, get a list of the url of all items in the album
     * @param  albumID the id of the album
     * @return a list of urls for the items in the album. The urls are the
     * absolute path of the items
     */
    TQStringList getItemURLsInAlbum(int albumID);

    /**
     * Given a albumID, get a list of Ids of all items in the album
     * @param  albumID the id of the album
     * @return a list of Ids for the items in the album.
     */
    LLongList getItemIDsInAlbum(int albumID);

    /**
     * Returns all items in the database without a date. This is used
     * in the scanlib class which tries to find out the date of the 
     * items, so the database holds the date for each item. This was
     * not the case untill the 0.8.0 release.
     * @return The path (starting from albumPath and including the 
     * the filename of all items.
     */
    TQStringList getAllItemURLsWithoutDate();

    /**
     * Given a tagid, get a list of the url of all items in the tag
     * @param  tagID the id of the tag
     * @param  recursive perform a recursive folder hierarchy parsing
     * @return a list of urls for the items in the tag. The urls are the
     * absolute path of the items
     */
    TQStringList getItemURLsInTag(int tagID, bool recursive = false);

    /**
     * Given a tagID, get a list of Ids of all items in the tag
     * @param  tagID the id of the tag
     * @param  recursive perform a recursive folder hierarchy parsing
     * @return a list of Ids for the items in the tag.
     */
    LLongList getItemIDsInTag(int tagID, bool recursive = false);

    /**
     * Given an albumid, this returns the url for that albumdb
     * @param albumID the id of the albumdb
     * @return the url of the albumdb
     */
    TQString getAlbumURL(int albumID);

    /**
     * Returns the lowest/oldest date of all images for that album.
     * @param albumID the id of the album to calculate
     * @return the date.
     */
    TQDate getAlbumLowestDate(int albumID);

    /**
     * Returns the highest/newest date of all images for that album.
     * @param albumID the id of the album to calculate
     * @return the date.
     */
    TQDate getAlbumHighestDate(int albumID);

    /**
     * Returns the average date of all images for that album.
     * @param albumID the id of the album to calculate
     * @return the date.
     */
    TQDate getAlbumAverageDate(int albumID);

    /**
     * Move the attributes of an item to a different item. Useful when
     * say a file is renamed
     * @param  srcAlbumID the id of the source album
     * @param  dstAlbumID the id of the destination album
     * @param  srcName    the name of the source file
     * @param  dstName    the name of the destination file
     */
    void moveItem(int srcAlbumID, const TQString& srcName,
                  int dstAlbumID, const TQString& dstName);

    /**
     * Copy the attributes of an item to a different item. Useful when
     * say a file is copied.
     * The operation fails (returns -1) of src and dest are identical.
     * @param  srcAlbumID the id of the source album
     * @param  dstAlbumID the id of the destination album
     * @param  srcName    the name of the source file
     * @param  dstName    the name of the destination file
     * @return the id of item added or -1 if it fails
     */
    int copyItem(int srcAlbumID, const TQString& srcName,
                 int dstAlbumID, const TQString& dstName);

    /**
     * This will execute a given SQL statement to the database.
     * @param sql The SQL statement
     * @param values This will be filled with the result of the SQL statement
     * @param debug If true, it will output the SQL statement 
     * @return It will return if the execution of the statement was succesfull
     */
    bool execSql(const TQString& sql, TQStringList* const values = 0, 
                 const bool debug = false);

    /**
     * To be used only if you are sure of what you are doing
     * @return the last inserted row in one the db table.
     */
    TQ_LLONG lastInsertedRow();

private:

    /**
     * Checks the available tables and creates them if they are not 
     * available.
     */
    void initDB();

    /**
     * Escapes text fields. This is needed for all queries to the database
     * which happens with an argument which is a text field. It makes sure
     * a ' is replaced with '', as this is needed for sqlite.
     * @param str String to escape
     * @return The escaped string
     */
    TQString escapeString(TQString str) const;

private:

    AlbumDBPriv* d;
};

}  // namespace Digikam

#endif /* ALBUMDB_H */
