/***************************************************************************
    copyright            : (C) 2003-2006 by Robby Stephenson
    email                : robby@periapsis.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of version 2 of the GNU General Public License as  *
 *   published by the Free Software Foundation;                            *
 *                                                                         *
 ***************************************************************************/

#ifndef IMAGEFACTORY_H
#define IMAGEFACTORY_H

#include "stringset.h"

#include <kurl.h>

#include <tqcolor.h>
#include <tqcache.h>

class KTempDir;

namespace Tellico {
  namespace Data {
    class Image;
    class ImageInfo;
  }

class StyleOptions {
public:
  TQString fontFamily;
  int fontSize;
  TQColor baseColor;
  TQColor textColor;
  TQColor highlightedBaseColor;
  TQColor highlightedTextColor;
  TQString imgDir;
};

/**
 * @author Robby Stephenson
 */
class ImageFactory {
public:
  enum CacheDir {
    TempDir,
    DataDir,
    LocalDir
  };

  /**
   * setup some of the static members
   */
  static void init();

  /**
   * Returns the temporary directory where image files are saved
   *
   * @return The full path
   */
  static TQString tempDir();
  static TQString dataDir();

  /**
   * Add an image, reading it from a URL, which is the case when adding a new image from the
   * @ref ImageWidget.
   *
   * @param url The URL of the image, anything TDEIO can handle
   * @param quiet If any error should not be reported.
   * @return The image id, empty if null
   */
  static TQString addImage(const KURL& url, bool quiet=false,
                          const KURL& referrer = KURL(), bool linkOnly=false);
  /**
   * Add an image, reading it from a regular TQImage, which is the case when dragging and dropping
   * an image in the @ref ImageWidget. The format has to be included, since the TQImage doesn't
   * 'know' what format it came from.
   *
   * @param image The qimage
   * @param format The image format, probably "PNG"
   * @return The image id, empty if null
   */
  static TQString addImage(const TQImage& image, const TQString& format);
  static TQString addImage(const TQPixmap& image, const TQString& format);
  /**
   * Add an image, reading it from data, which is the case when reading from the data file. The
   * @p id isn't strictly needed, since it can be reconstructed from the image data and format, but
   * since it's already known, go ahead and use it.
   *
   * @param data The image data
   * @param format The image format, from TQt's output format list
   * @param id The internal id of the image
   * @return The image id, empty if null
   */
  static TQString addImage(const TQByteArray& data, const TQString& format, const TQString& id);

  /**
   * Writes an image to a file. ImageFactory keeps track of which images were already written
   * if the location is the same as the tempdir.
   *
   * @param id The ID of the image to be written
   * @param targetDir The directory to write the image to, if empty, the tempdir is used.
   * @param force Force the image to be written, even if it already has been
   * @return Whether the save was successful
   */
  static bool writeImage(const TQString& id, const KURL& targetDir, bool force=false);
  static bool writeCachedImage(const TQString& id, CacheDir dir, bool force = false);

  /**
   * Returns an image reference given its id. If none is found, a null image
   * is returned.
   *
   * @param id The image id
   * @return The image referencenter
   */
  static const Data::Image& imageById(const TQString& id);
  static Data::ImageInfo imageInfo(const TQString& id);
  static void cacheImageInfo(const Data::ImageInfo& info);
  // basically returns !imageById().isNull()
  static bool validImage(const TQString& id);

  static TQPixmap pixmap(const TQString& id, int w, int h);

  /**
   * Clear the image cache and dict
   * if deleteTempDirectory = true, then clean the temp dir and remove all temporary image files
   */
  static void clean(bool deleteTempDirectory);
  /**
   * Creates the gradient images used in the entry view.
   */
  static void createStyleImages(const StyleOptions& options = StyleOptions());

  static void removeImage(const TQString& id_, bool deleteImage);
  static StringSet imagesNotInCache();

  static void setLocalDirectory(const KURL& url);
  // local save directory
  static TQString localDir();

private:
  /**
   * Add an image, reading it from a URL, which is the case when adding a new image from the
   * @ref ImageWidget.
   *
   * @param url The URL of the image, anything TDEIO can handle
   * @param quiet If any error should not be reported.
   * @return The image
   */
  static const Data::Image& addImageImpl(const KURL& url, bool quiet=false,
                                         const KURL& referrer = KURL(), bool linkOnly = false);
  /**
   * Add an image, reading it from a regular TQImage, which is the case when dragging and dropping
   * an image in the @ref ImageWidget. The format has to be included, since the TQImage doesn't
   * 'know' what format it came from.
   *
   * @param image The qimage
   * @param format The image format, probably "PNG"
   * @return The image
   */
  static const Data::Image& addImageImpl(const TQImage& image, const TQString& format);
  /**
   * Add an image, reading it from data, which is the case when reading from the data file. The
   * @p id isn't strictly needed, since it can be reconstructed from the image data and format, but
   * since it's already known, go ahead and use it.
   *
   * @param data The image data
   * @param format The image format, from TQt's output format list
   * @param id The internal id of the image
   * @return The image
   */
  static const Data::Image& addImageImpl(const TQByteArray& data, const TQString& format, const TQString& id);

  static const Data::Image& addCachedImageImpl(const TQString& id, CacheDir dir);
  static bool hasImage(const TQString& id);
  static void releaseImages();

  static bool s_needInit;
  static TQDict<Data::Image> s_imageDict;
  static TQCache<Data::Image> s_imageCache;
  static TQCache<TQPixmap> s_pixmapCache;
  static TQMap<TQString, Data::ImageInfo> s_imageInfoMap;
  static StringSet s_imagesInTmpDir; // the id's of the images written to tmp directory
  static StringSet s_imagesToRelease;
  static KTempDir* s_tmpDir;
  static TQString s_localDir;
  static const Data::Image s_null;
};

} // end namespace

#endif
