/***************************************************************************
 *   Copyright 2008 Last.fm Ltd. <client@last.fm>                          *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   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.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA  02110-1301, USA.          *
 ***************************************************************************/

#ifndef ITUNES_TRACK_H
#define ITUNES_TRACK_H

#include "ITunesExceptions.h"

#ifdef WIN32
    #include "../iTunesCOMAPI/iTunesCOMInterface.h"

    // Disable gay warning about exception specifications
    #pragma warning( disable : 4290 )
#endif

#include <string>


/** @author Max Howell <max@last.fm> -- mac
  * @author Erik Jalevik <erik@last.fm> -- windows
  * @brief Uses AppleScript or COM to retrieve properties of an iTunes track.
  *        All functions that access COM directly will throw an ITunesException
  *        if something went wrong.
  */
class ITunesTrack
{
public:
  #ifdef WIN32

    ITunesTrack(); // creates a null track
      
    /** Creates a track from a COM track object. Ownership is passed to this
      * class and it will call Release on the object when done. Never throws. */
    ITunesTrack( IITTrack* track );

    // Copy ctor (needed because of owned COM pointer)
    ITunesTrack( const ITunesTrack& that );
    ITunesTrack& operator=( const ITunesTrack& that );
    
    ITunesTrack::~ITunesTrack();

    /** Unicode */
    std::wstring track() const;
    std::wstring artist() const;
    std::wstring album() const;

    /** Date format: "YYYY-MM-DD HH:MM:SS", returns an empty string if track was never played */
    std::wstring lastPlayed() const;

    /** In seconds */
    long duration() const;
    
    /** Convenience function for logging etc */
    std::wstring toString() const { return artist() + L" - " + track(); }

    /** Uses runtime ID to compare the two. */
    bool isSameAs( const ITunesTrack& that );

    /** These two fields are always populated when an iTunes track is created */
    std::wstring persistentId() const { return m_id; }
    std::wstring path() const { return m_path; }

  #else
      
    /** These two fields are always populated when an iTunes track is created */
    std::string persistentId() const { return m_id; }
    std::string path() const { return m_path; }
  
  #endif

    /** The below fields are real-time */
    long playCount() const throw( PlayCountException );
    bool isNull() const;

protected:

  #ifdef WIN32

    std::wstring m_id;
    std::wstring m_path;

    std::wstring pathForTrack( IITTrack* track );
    void clone( const ITunesTrack& that );

    IITTrack* m_comTrack;

  #else

    std::string m_id; // utf8
    std::string m_path; // utf8

    /** executes an applescript in the bundle and returns the output */
    static std::string scriptResult( const char* filename, const std::string& argv1 = "" ) throw();

  #endif  
};


/** @author Max Howell <max@last.fm>
  * @brief Specialised variety of ITunesTrack, used for playCount sync 
  *   operations, where we need the difference in playCount since the object was
  *   initialised */
class ExtendedITunesTrack : public ITunesTrack
{
public:
    ExtendedITunesTrack() : m_initialPlayCount( -2 )
    {}
    
#ifdef WIN32
    static ExtendedITunesTrack from( const ITunesTrack& that )
    {
		ExtendedITunesTrack t;
		t.ITunesTrack::operator=( that );
        t.m_initialPlayCount = that.playCount();
        return t;
    }
#else
    /** returns the track currently playing in iTunes */
    static ExtendedITunesTrack currentTrack();
#endif

    int playCountDifference() const throw( PlayCountException );
    int initialPlayCount() const { return m_initialPlayCount; }
    void setInitialPlaycount( int pc ) { m_initialPlayCount = pc; }
    
private:
    int m_initialPlayCount;
};

#endif // ITUNESTRACK_H
