#ifndef CONFIG_H
#define CONFIG_H

#include "formatinfoloader.h"
#include "conversionoptions.h"

#include <tqobject.h>
#include <tqvaluelist.h>
#include <tqstringlist.h>
#include <tqmap.h>

class Logger;
class ConvertPlugin;
//class ConvertPluginLoader;
class ReplayGainPlugin;
//class ReplayGainPluginLoader;
class RipperPlugin;
struct ProfileData;


/**
 * @short Format items for the format list
 * @author Daniel Faust <hessijames@gmail.com>
 * @version 0.3
 */
class FormatItem
{
public:
    /**
     * Constructor
     */
    FormatItem();

    /**
     * Destructor
     */
    virtual ~FormatItem();

    TQStringList mime_types;
    TQStringList extensions; // for easy use
    TQStringList correction_file_mime_types;
    TQStringList correction_file_extensions; // for easy use
    TQString description;
    FormatInfo::CompressionType compressionType;
    int compressionLevel; // the value from the config dialog
    bool internalReplayGain;
    int size;
    TQValueList<ConvertPlugin*> encoders;
    TQValueList<ConvertPlugin*> decoders;
    TQValueList<ReplayGainPlugin*> replaygains;
    //TQValueList<RepairerPlugin*> repairers;
    ConvertPlugin* encoder;
    ConvertPlugin* decoder;
    ReplayGainPlugin* replaygain;
    //RepairerPlugin* repairer;
};


/**
 * @short Configuration class
 * @author Daniel Faust <hessijames@gmail.com>
 * @version 0.3
 */
class Config : public TQObject
{
    Q_OBJECT
  
public:
    /**
     * Constructor
     */
    Config( Logger* );

    /**
     * Destructor
     */
    virtual ~Config();

    /**
     * Read the preferences from the configuration file
     */
    void read();

    /**
     * Write the preferences to the configuration file
     */
    void write( bool sync = true );

    /**
     * Read the profiles from the profiles file
     */
    void readProfiles();

    /**
     * Write the profiles to the profiles file
     */
    void writeProfiles();

    /**
     * Get the encoder for a given file format (mime type or extension)
     */
    ConvertPlugin* encoderForFormat( const TQString &format );

    /**
     * Get the decoder for a given file format (mime type or extension)
     */
    ConvertPlugin* decoderForFormat( const TQString &format );

    /**
     * Get the decoder for a given file format (mime type or extension)
     */
    ReplayGainPlugin* replaygainForFormat( const TQString &format );

    /**
     * Get the format information for a given file format (mime type or extension)
     */
    FormatItem* getFormatItem( const TQString &format );

    /**
     * Get the current ripper
     */
    RipperPlugin* getCurrentRipper() { return currentRipper; }

    /**
     * Set the current ripper
     */
    void setCurrentRipper( RipperPlugin* ripper ) { currentRipper = ripper; }

    /**
     * Returns a list of all loaded rippers
     */
    TQValueList<RipperPlugin*> allRippers() { return rippers; }

    /**
     * Returns a list of all loaded converters
     */
    TQValueList<ConvertPlugin*> allConverters() { return converters; }

    /**
     * Returns a list of all loaded replaygains
     */
    TQValueList<ReplayGainPlugin*> allReplayGains() { return replaygains; }

    /**
     * Returns a list of all known file formats
     */
    TQStringList allFormats();

    /**
     * Returns a list of all known encodeable file formats
     */
    TQStringList allEncodableFormats();

    /**
     * Returns a list of all known lossy encodeable file formats
     */
    TQStringList allLossyEncodableFormats();

    /**
     * Returns a list of all known lossless encodeable file formats
     */
    TQStringList allLosslessEncodableFormats();

    /**
     * Returns a list of all known hybrid encodeable file formats
     */
    TQStringList allHybridEncodableFormats();

    /**
     * Returns the extension of the correction file format for the given format
     * If there is nor correction file format, the returned string is empty
     */
    TQString getCorrectionExtension( const TQString &format );

    /**
     * Returns a localized description for the given format
     */
    TQString getFormatDescription( const TQString &format );

    /**
     * Add a new profile
     */
    void addProfile( const TQString &name, const ConversionOptions& profile );

    /**
     * Remove a new profile
     */
    void removeProfile( const TQString &name );

    /**
     * Returns the conversion options for a profile
     */
    ConversionOptions getProfile( const TQString &name );

    /**
     * Returns the name of the profile with conversion options @p options
     */
     TQString getProfileName( const ConversionOptions& options );

    /**
     * Returns a list of all user defined profiles
     */
    TQStringList getAllProfiles();

    /**
     * Returns true if the @p file can be added to the conversion list (can be decoded)
     */
    bool acceptFile( const TQString& format );

    /**
     * Returns true if the @p file can be added to the replay gain tool
     */
    bool acceptReplayGainFile( const TQString& format );

    /**
     * Returns a file filter suitable for the file open dialog
     */
    TQString fileFilter( bool wav = true );

    /**
     * Returns a string list of supported file formats
     */
    TQStringList fileTypes( bool wav = true );

    /**
     * Returns a file filter suitable for the file open dialog for the replay gain scanner
     */
    TQString replayGainFilter();

    /**
     * Returns a string list of Replay Gain supported file formats
     */
    TQStringList replayGainFileTypes();

    struct Data {
        struct General {
            int startTab;
            int lastTab;
            TQString defaultProfile;
            TQString defaultFormat;
//             TQString defaultOutputDirectory;
            TQString specifyOutputDirectory;
            TQString metaDataOutputDirectory;
            TQString copyStructureOutputDirectory;
            int priority;
            bool useVFATNames;
            int conflictHandling;
            int numFiles;
            int updateDelay;
            bool askForNewOptions;
            bool executeUserScript;
            bool showToolBar;
        } general;
        struct Plugins {
            bool checkForUpdates;
        } plugins;
        struct Environment {
            TQStringList directories;
            TQStringList foundPrograms;
        } environment;
        struct App {
            int configVersion;
        } app;
    } data;

    bool onlinePluginsChanged;
    bool backendsChanged;

    TQMap<TQString, TQString> binaries;

private:
    struct PluginMapData {
        int version;
        TQString filename;
        TQString type;
    };

    Logger* logger;

    /** holds all known formats */
    TQValueList<FormatItem> formats;

    /** holds all known rippers */
    TQValueList<RipperPlugin*> rippers;
    RipperPlugin* currentRipper;

    /** holds all known converters */
    TQValueList<ConvertPlugin*> converters;
    /** holds all known replaygain apps */
    TQValueList<ReplayGainPlugin*> replaygains;
    /* holds all known file repairing apps */
//     TQValueList<RepairerItem> repairer;

    //ConvertPluginLoader* convertPluginLoader;
    //ReplayGainPluginLoader* replaygainPluginLoader;

    /** holds all user defined profiles */
    TQValueList<ProfileData> profiles;

    /**
     * Load the files with the file infos (format descriptions, file size, etc.)
     */
    void loadFileInfos();

    /**
     * Load all plugins that can be found
     */
    void loadPlugins();

    /**
     * A plugin wants to register it's features for a file format
     * @p binary The binary name of the app that wants to register it's features
     * @p extension The file name extension for that is wants to register
     * @p features The features of the app for that extension
     */
    void registerFormatFeatures( const TQString &mime_type,
                                 ConvertPlugin* encoder = 0, ConvertPlugin* decoder = 0,
                                 ReplayGainPlugin* replaygain = 0/*, RepairPlugin* repairer = 0*/,
                                 const TQString &correction_file_mime_type = TQString() );

    /**
     * Generate the service menu
     */
    void writeServiceMenu();

    /**
     * Copy the amarok script
     */
    void writeAmarokScript();

    /*
     * We have new inforamtion for a file format
     * @p extension The file name extension for that is wants to register
     * @p newSynonym Register a new synonym for this file format?
     * @p newMimeType Register a new mime type for this file format?
     * @p newDescription Register a new description for this file format?
     * @p newSize Register a new size for this file format for calculating the progress?
     */
    /*void registerFileFormat( const TQString &extension, const TQString &newSynonym = TQString(),
                             const TQString &newMimeType = TQString(),
                             const TQString &newDescription = TQString(),
                             int newSize = 0, FormatInfo::CompressionType newCompressionType = FormatInfo::lossy );*/
    //void registerFileFormat( const TQString &mime_type, const TQString &option, const TQString &value );
    // NOTE this function is obsolete.
    //       after loading all plugins and creating all neccessary file format items,
    //       sk will search for format info files and update the items.

signals:
    void configChanged();

};

#endif // CONFIG_H