//See COPYING file for licensing information

#ifndef AMAROK_H
#define AMAROK_H

#include <tqnamespace.h>
#include <tqstring.h>

#include <kurl.h> // recursiveUrlExpand
#include <kprocio.h> //Amarok::ProcIO
#include <tdeio/netaccess.h>
#include <tdeversion.h>

#include "amarok_export.h"

class TDEActionCollection;
class TDEConfig;
class TQColor;
class TQDateTime;
class TQEvent;
class TQMutex;
class TQPixmap;
class TQWidget;
class DynamicMode;
class TQListView;
class TQListViewItem;
namespace TDEIO { class Job; }

namespace Amarok
{
    const int VOLUME_MAX = 100;
    const int SCOPE_SIZE = 9; //= 2**9 = 512
    const int blue       = 0xff202050;
    const int VOLUME_SENSITIVITY = 30; //for mouse wheels
    const int GUI_THREAD_ID = 0;

    extern TQMutex globalDirsMutex; // defined in app.cpp

    namespace ColorScheme
    {
        ///eg. base of the Amarok Player-window
        extern TQColor Base; //Amarok::blue
        ///eg. text in the Amarok Player-window
        extern TQColor Text; //TQt::white
        ///eg. background colour for Amarok::PrettySliders
        extern TQColor Background; //brighter blue
        ///eg. outline of slider widgets in Player-window
        extern TQColor Foreground; //lighter blue
        ///eg. TDEListView alternative row color
        extern TQColor AltBase; //grey toned base
    }

    /** The version of the playlist XML format. Increase whenever it changes backwards-incompatibly. */
    inline TQString xmlVersion() { return "2.4"; }

    /**
     * Convenience function to return the TDEApplication instance TDEConfig object
     * pre-set to a specific group.
     * @param group Will pre-set the TDEConfig object to this group.
     */
    /* FIXME: This function can lead to very bizarre and hard to figure bugs.
              While we don`t fix it properly, use it like this: amarok::config( Group )->readNumEntry( ... ) */
    TDEConfig *config( const TQString &group = "General" ); //defined in app.cpp

    /**
     * @return the TDEActionCollection used by Amarok
     * The TDEActionCollection is owned by the PlaylistWindow, so you must ensure
     * you don't try to use this before then, but we've taken steps to prevent
     * this eventuality - you should be safe.
     */
    TDEActionCollection *actionCollection(); //defined in app.cpp

    /**
     * An event handler that handles events in a generic Amarok fashion. Mainly
     * useful for drops, ie offers the Amarok popup for adding tracks to the
     * playlist. You shouldn't pass every event here, ie closeEvents will not be
     * handled as expected! Check the source in app.cpp if you want to see what
     * it can do.
     * @param recipient The object that received the event.
     * @param e The event you want handled in a generic fashion.
     * @return true if the event was handled.
     */
    bool genericEventHandler( TQWidget *recipient, TQEvent *e ); //defined in app.cpp

    /**
     * Invoke the external web browser set in Amarok's configuration.
     * @param url The URL to be opened in the browser.
     * @return True if the browser could be started.
     */
    bool invokeBrowser( const TQString& url ); //defined in app.cpp

    /**
     * Obtain an Amarok PNG image as a TQPixmap
     */
    TQPixmap getPNG( const TQString& /*fileName*/ ); //defined in app.cpp

    /**
     * Obtain an Amarok JPG image as a TQPixmap
     */
    TQPixmap getJPG( const TQString& /*fileName*/ ); //defined in app.cpp

    /**
     * The mainWindow is the playlistWindow or the playerWindow depending on
     * the configuration of Amarok
     */
    TQWidget *mainWindow(); //defined in app.cpp

    /**
     * Allocate one on the stack, and it'll set the busy cursor for you until it
     * is destroyed
     */
    class OverrideCursor { //defined in app.cpp
    public:
        OverrideCursor( TQt::CursorShape cursor = TQt::WaitCursor );
       ~OverrideCursor();
    };

    /**
     * For saving files to ~/.trinity/share/apps/amarok/directory
     * @param directory will be created if not existing, you MUST end the string
     *                  with '/'
     */
    LIBAMAROK_EXPORT TQString saveLocation( const TQString &directory = TQString() ); //defined in collectionreader.cpp

    TDEIO::Job *trashFiles( const KURL::List &files ); //defined in app.cpp

    /**
     * For recursively expanding the contents of a directory into a KURL::List
     * (playlists are ignored)
     */
    LIBAMAROK_EXPORT KURL::List recursiveUrlExpand( const KURL &url, int maxURLs = -1 ); //defined in playlistloader.cpp
    LIBAMAROK_EXPORT KURL::List recursiveUrlExpand( const KURL::List &urls, int maxURLs = -1 ); //defined in playlistloader.cpp

    TQString verboseTimeSince( const TQDateTime &datetime ); //defined in contextbrowser.cpp

    TQString verboseTimeSince( uint time_t ); //defined in contextbrowser.cpp

    /**
     * Function that must be used when separating contextBrowser escaped urls
     */
    // defined in contextbrowser.cpp
    void albumArtistTrackFromUrl( TQString url, TQString &artist, TQString &album, TQString &detail );

    /**
     * @return the LOWERCASE file extension without the preceding '.', or "" if there is none
     */
    inline TQString extension( const TQString &fileName )
    {
        return fileName.contains( '.' ) ? fileName.mid( fileName.findRev( '.' ) + 1 ).lower() : "";
    }

    /** Transform url into a file url if possible */
    inline KURL mostLocalURL( const KURL &url )
    {
#if TDE_VERSION < TDE_MAKE_VERSION(3,5,0)
        return url;
#else
        return TDEIO::NetAccess::mostLocalURL( url, mainWindow() );
#endif
    }

    /**
     * @return the last directory in @param fileName
     */
    inline TQString directory( const TQString &fileName )
    {
        return fileName.section( '/', 0, -2 );
    }
  /** Due to xine-lib, we have to make TDEProcess close all fds, otherwise we get "device is busy" messages
  * Used by Amarok::ProcIO and Amarok::Process, exploiting commSetupDoneC(), a virtual method that
  * happens to be called in the forked process
  * See bug #103750 for more information.
  */
  //TODO ugly hack, fix TDEProcess for KDE 4.0
    LIBAMAROK_EXPORT void closeOpenFiles(int out, int in, int err); //defined in scriptmanager.cpp

    /**
    * Returns internal code for database type, DbConnection::sqlite, DbConnection::mysql, or DbConnection::postgresql
    * @param type either "SQLite", "MySQL", or "Postgresql".
    */
    int databaseTypeCode( const TQString type ); //defined in configdialog.cpp

    void setUseScores( bool use ); //defined in app.cpp
    void setUseRatings( bool use );
    void setMoodbarPrefs( bool show, bool moodier, int alter, bool withMusic );

    bool repeatNone(); //defined in actionclasses.cpp
    bool repeatTrack();
    bool repeatAlbum();
    bool repeatPlaylist();
    bool randomOff();
    bool randomTracks();
    bool randomAlbums();
    bool favorNone();
    bool favorScores();
    bool favorRatings();
    bool favorLastPlay();
    bool entireAlbums(); //repeatAlbum() || randomAlbums()

    const DynamicMode *dynamicMode(); //defined in playlist.cpp

    TQListViewItem* findItemByPath( TQListView *view, TQString path ); //defined in playlistbrowser.cpp
    TQStringList splitPath( TQString path ); //defined in playlistbrowser.cpp

    /**
     * Creates a copy of of the KURL instance, that doesn't have any TQStrings sharing memory.
    **/
    KURL detachedKURL( const KURL &url ); //defined in metabundle.cpp

    /**
     * Maps the icon name to a system icon or custom Amarok icon, depending on the settings.
     */
    LIBAMAROK_EXPORT TQString icon( const TQString& name ); //defined in iconloader.cpp

    /**
     * Removes accents from the string
     * @param path The original path.
     * @return The cleaned up path.
     */
    LIBAMAROK_EXPORT TQString cleanPath( const TQString &path ); //defined in app.cpp

    /**
     * Replaces all non-ASCII characters with '_'.
     * @param path The original path.
     * @return The ASCIIfied path.
     */
    LIBAMAROK_EXPORT TQString asciiPath( const TQString &path ); //defined in app.cpp

    /**
     * Transform path into one valid on VFAT file systems
     * @param path The original path.
     * @return The cleaned up path.
     */
    LIBAMAROK_EXPORT TQString vfatPath( const TQString &path ); //defined in app.cpp

    /**
     * Compare both strings from left to right and remove the common part from input
     * @param input the string that get's cleaned.
     * @param ref a reference to compare input with.
     * @return The cleaned up string.
     */
    LIBAMAROK_EXPORT TQString decapitateString( const TQString &input, const TQString &ref );

    /*
     * Transform to be usable within HTML/HTML attributes
     * defined in contextbrowser.cpp
     */
    LIBAMAROK_EXPORT TQString escapeHTML( const TQString &s );
    LIBAMAROK_EXPORT TQString escapeHTMLAttr( const TQString &s );
    LIBAMAROK_EXPORT TQString unescapeHTMLAttr( const TQString &s );

    /* defined in scriptmanager.cpp */
    /**
     * Returns the proxy that should be used for a given URL.
     * @param url the url.
     * @return The url of the proxy, or a empty string if no proxy should be used.
     */
    LIBAMAROK_EXPORT TQString proxyForUrl(const TQString& url);

    /**
     * Returns the proxy that should be used for a given protocol.
     * @param protocol the protocol.
     * @return The url of the proxy, or a empty string if no proxy should be used.
     */
    LIBAMAROK_EXPORT TQString proxyForProtocol(const TQString& protocol);

    ////////////////////////////////////////////////////////////////////////////////
    // class Amarok::ProcIO
    ////////////////////////////////////////////////////////////////////////////////
    /**
    * Due to xine-lib, we have to make TDEProcess close all fds, otherwise we get "device is busy" messages
    * Used by Amarok::ProcIO and AmarokProcess, exploiting commSetupDoneC(), a virtual method that
    * happens to be called in the forked process
    * See bug #103750 for more information.
    */
    class LIBAMAROK_EXPORT ProcIO : public KProcIO {
        public:
        ProcIO(); // ctor sets the textcodec to UTF-8, in scriptmanager.cpp
        virtual int commSetupDoneC() {
            const int i = KProcIO::commSetupDoneC();
            Amarok::closeOpenFiles( KProcIO::out[0],KProcIO::in[0],KProcIO::err[0] );
            return i;
        };
    };

    ////////////////////////////////////////////////////////////////////////////////
    // class Amarok::Process
    ////////////////////////////////////////////////////////////////////////////////
    /** Due to xine-lib, we have to make TDEProcess close all fds, otherwise we get "device is busy" messages
     * Used by Amarok::ProcIO and Amarok::Process, exploiting commSetupDoneC(), a virtual method that
     * happens to be called in the forked process
     * See bug #103750 for more information.
     */
    class LIBAMAROK_EXPORT Process : public TDEProcess {
        public:
        Process( TQObject *parent = 0 ) : TDEProcess( parent ) {}
        virtual int commSetupDoneC() {
            const int i = TDEProcess::commSetupDoneC();
            Amarok::closeOpenFiles(TDEProcess::out[0],TDEProcess::in[0], TDEProcess::err[0]);
            return i;
        };
    };


}

#ifdef USE_QT4
#undef foreach
#endif // USE_QT4

/**
 * Use this to const-iterate over TQStringLists, if you like.
 * Watch out for the definition of last in the scope of your for.
 *
 *     TQStringList strings;
 *     foreach( strings )
 *         debug() << *it << endl;
 */
#define foreach( x ) \
    for( TQStringList::ConstIterator it = x.begin(), end = x.end(); it != end; ++it )

/**
 * You can use this for lists that aren't TQStringLists.
 * Watch out for the definition of last in the scope of your for.
 *
 *     BundleList bundles;
 *     foreachType( BundleList, bundles )
 *         debug() << *it.url() << endl;
 */
#define foreachType( Type, x ) \
    for( Type::ConstIterator it = x.begin(), end = x.end(); it != end; ++it )

/**
 * Creates iterators of type @p Type.
 * Watch out for the definitions of last and end in your scope.
 *
 *     BundleList bundles;
 *     for( for_iterators( BundleList, bundles ); it != end; ++it )
 *         debug() << *it.url() << endl;
 */
#define for_iterators( Type, x ) \
    Type::ConstIterator it = x.begin(), end = x.end(), last = x.fromLast()


/// Update this when necessary
#define APP_VERSION "1.4.10"

#endif
