/***************************************************************************
 * copyright            : (C) 2006 Ian Monroe <ian@monroe.nu>              *
 *                        (C) 2006 Seb Ruiz <me@sebruiz.net>               *
 **************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef AMAROK_DAAPCLIENT_H
#define AMAROK_DAAPCLIENT_H

#include "daapreader/reader.h"
#include "mediabrowser.h"
#include "threadmanager.h"

#include <tdeversion.h>
#include <kdialogbase.h>
#include <tdetempfile.h>

#define DNSSD_SUPPORT KDE_IS_VERSION(3,4,0)

#if DNSSD_SUPPORT
    #include <dnssd/remoteservice.h> //for DNSSD::RemoteService::Ptr
#else
namespace DNSSD {
    namespace RemoteService {
        class Ptr {}; //HACK Dummy class, so that daapclient.moc compiles
    }
}
#endif

namespace DNSSD {
    class ServiceBrowser;
}

class AddHostBase;
class MediaItem;
class ServerItem;
class DaapServer;

class KURL;

class TQCheckBox;
class TQString;
class TQTimer;

class DaapClient : public MediaDevice
{
    Q_OBJECT
  
   public:
        struct ServerInfo
        {
            ServerInfo() : sessionId( -1 ), revisionID( 10 ) { }
            int sessionId;
            int revisionID;
        };

        DaapClient();
        virtual ~DaapClient();
        bool isConnected();

        virtual bool needsManualConfig() { return true; }
        virtual void addConfigElements   ( TQWidget * /*parent*/ );
        virtual void removeConfigElements( TQWidget * /*parent*/ );
        virtual void applyConfig();
        virtual void loadConfig();


        int incRevision( const TQString& host );
        int getSession( const TQString& host );
        KURL getProxyUrl( const KURL& url );
        void customClicked();
        bool autoConnect() { return true; }

    public slots:
         void passwordPrompt();

    protected:
         bool getCapacity( TDEIO::filesize_t *total, TDEIO::filesize_t *available );
         void rmbPressed( TQListViewItem* qitem, const TQPoint& point, int );
         bool lockDevice( bool tryOnly = false );
         void unlockDevice();
         bool openDevice( bool silent=false );
         bool closeDevice();
         void synchronizeDevice();
         MediaItem* copyTrackToDevice(const MetaBundle& bundle);
         MediaItem* trackExists( const MetaBundle& );
         virtual int deleteItemFromDevice( MediaItem *item, int flags=DeleteTrack );

   private slots:
        void serverOffline( DNSSD::RemoteService::Ptr );
        void foundDaap( DNSSD::RemoteService::Ptr );
        void resolvedDaap( bool );
        void createTree( const TQString& host, Daap::SongList bundles );
        void broadcastButtonToggled();

   private:
        ServerItem* newHost( const TQString& serviceName, const TQString& host, const TQString& ip, const TQ_INT16 port );
        void downloadSongs( KURL::List urls );
        TQString resolve( const TQString& hostname );
#if DNSSD_SUPPORT
        TQString serverKey( const DNSSD::RemoteService* service ) const;
        DNSSD::ServiceBrowser* m_browser;
#endif
        /// @return true if track is already in the local collection
        const bool trackExistsInCollection( MetaBundle *bundle );

        bool    m_connected;
        TQMap<TQString, ServerInfo*> m_servers;
        TQMap<TQString, ServerItem*> m_serverItemMap;

        DaapServer *m_sharingServer;
        TQCheckBox  *m_broadcastServerCheckBox;
        TQCheckBox  *m_removeDuplicatesCheckBox;
        bool        m_broadcastServer;
        bool        m_removeDuplicates;
        TDEToolBarButton *m_broadcastButton;

        // if set to true, we don't display items that the user already has in the collection
        bool        m_hideMusicOwned;
};

class ServerItem : public TQObject, public MediaItem
{
    Q_OBJECT
  

    public:
        ServerItem( TQListView* parent, DaapClient* client, const TQString& ip, TQ_UINT16 port, const TQString& title, const TQString& host );
        ~ServerItem();
        void setOpen( bool o );
        void resetTitle()                     { setText( 0, m_title ); }
        void unLoaded()                       { m_loaded = false; }
        void setReader( Daap::Reader* reader) { m_reader = reader; }
        Daap::Reader* getReader() const       { return m_reader; }

        void startAnimation();
        void stopAnimation();

        TQString key() const { return key( m_host, m_port ); }
        void reset();
        static TQString key( const TQString& host, TQ_UINT16 port ) { return host + ':' + TQString::number( port ); }
    public slots:
        void httpError( const TQString& );
    private slots:
        void slotAnimation();

    private:
        DaapClient     *m_daapClient;
        Daap::Reader   *m_reader;
        const TQString   m_ip;
        const TQ_UINT16  m_port;
        const TQString   m_title;
        const TQString   m_host;
        bool            m_loaded;

        TQPixmap        *m_loading1, *m_loading2;    //icons for loading animation
        TQTimer          m_animationTimer;
        uint            m_iconCounter;

        static const int ANIMATION_INTERVAL = 250;
};

#ifdef Q_MOC_RUN
// MOC_SKIP_BEGIN
class DaapDownloader : public JobBase
// MOC_SKIP_END
#else
class DaapDownloader : public ThreadManager::Job
#endif
{
Q_OBJECT
  
public:
    DaapDownloader( KURL::List urls );

    virtual bool doJob();

    virtual void completeJob();

private slots:
    void downloadFinished( int id, bool error );
    void dataReadProgress( int done, int total );
    void downloadFailed( const TQString &error );

private:
    KURL::List m_urls;
    TQValueList<KTempFile*> m_tempFileList;
    bool m_ready;
    bool m_successful;
    bool m_errorOccured;
};

#endif /*AMAROK_DAAPCLIENT_H*/
