/*
 * winamptunecontroller.cpp
 * Copyright (C) 2006  Remko Troncon
 *
 * 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

#include <windows.h>

#ifdef Q_CC_MSVC
#pragma warning(push)
#pragma warning(disable: 4100)
#endif

// this file generates eight C4100 warnings, when compiled with MSVC2003
#include "plugins/winamp/third-party/wa_ipc.h"

#ifdef Q_CC_MSVC
#pragma warning(pop)
#endif

#include "winamptunecontroller.h"


/**
 * \class WinAmpTuneController
 * \brief A controller for WinAmp.
 */

static const int NormInterval = 3000;
static const int AntiscrollInterval = 100;

/**
 * \brief Constructs the controller.
 */
WinAmpTuneController::WinAmpTuneController()
: PollingTuneController(),
  antiscrollCounter_(0)
{
	startPoll();
	setInterval(NormInterval);
}

template <typename char_type> const size_t length (const char_type * begin)
{
	const char_type * end = begin;
	for (; *end; ++end);
	return end - begin;
}

// Returns a title of a track currently being played by WinAmp with given HWND (passed in waWnd)
QPair<bool, QString> WinAmpTuneController::getTrackTitle(const HWND &waWnd) const
{
	TCHAR waTitle[2048];
	QString title;

	// Get WinAmp window title. It always contains name of the track
	SendMessage (waWnd, WM_GETTEXT, static_cast<WPARAM> (sizeof (waTitle) / sizeof (waTitle[0])), reinterpret_cast<LPARAM> (waTitle));
	// Now, waTitle contains WinAmp window title
	title = QString ((const QChar *) waTitle, length<TCHAR> ((const TCHAR *) waTitle));
	if (title[0] == '*' || (title.length () && title[title.length() - 1] == '*')) {
		// request to be called again soon.
		return QPair<bool, QString>(false, QString());
	}

	// Check whether there is a need to do the all stuff
	if (!title.length()) {
		return QPair<bool, QString>(true,title);
	}

	QString winamp (" - Winamp ***");
	int winampLength = winamp.length();

	// Is title scrolling on the taskbar enabled?
	title += title + title;
	int waLast = title.indexOf (winamp, -1);
	if (waLast != -1) {
		if (title.length()) {
			title.remove (waLast, title.length () - waLast);
		}
		int waFirst;
		while ((waFirst = title.indexOf (winamp)) != -1) {
			title.remove (0, waFirst + winampLength);
		}
	}
	else {
		title = QString ((const QChar *) waTitle, length<TCHAR> ((const TCHAR *) waTitle)); // Title is not scrolling
	}

	// Remove leading and trailing spaces
	title  = title.trimmed();

	// Remove trailing " - Winamp" from title
	if (title.length ()) {
		winamp = " - Winamp";
		winampLength = winamp.length ();
		int waFirst = title.indexOf (winamp);
		if (waFirst != -1)
		{
			title.remove (waFirst, waFirst + winampLength);
		}
	}

	// Remove track number from title
	if (title.length ()) {
		QString dot(". ");
		int dotFirst = title.indexOf (dot);
		if (dotFirst != -1) {
			// All symbols before the dot are digits?
			bool allDigits = true;
			for (int pos = dotFirst; pos > 0; --pos) {
				allDigits = allDigits && title[pos].isNumber();
			}
			if (allDigits) {
				title.remove(0, dotFirst + dot.length ());
			}
		}
	}

	// Remove leading and trailing spaces
	if (title.length ()) {
		while (title.length () && title[0] == ' ') {
			title.remove (0, 1);
		}
		while (title.length () && title[title.length () - 1] == ' ') {
			title.remove (title.length () - 1, 1);
		}
	}

	return QPair<bool, QString>(true,title);
}


/**
 * Polls for new song info.
 */
void WinAmpTuneController::check()
{

	Tune tune;
#ifdef UNICODE
	HWND h = FindWindow(L"Winamp v1.x", NULL);
#else
	HWND h = FindWindow("Winamp v1.x", NULL);
#endif
	if (h && SendMessage(h, WM_WA_IPC, 0, IPC_ISPLAYING) == 1) {
		tune = getTune(h);
	}
	prevTune_ = tune;
	setInterval(NormInterval);
	PollingTuneController::check();
}

Tune WinAmpTuneController::getTune(const HWND &hWnd)
{
	Tune tune = Tune();
	int position = (int)SendMessage(hWnd, WM_WA_IPC, 0, IPC_GETLISTPOS);
	if (position != -1) {
		if (hWnd && SendMessage(hWnd,WM_WA_IPC,0,IPC_ISPLAYING) == 1) {
			QPair<bool, QString> trackpair(getTrackTitle(hWnd));
			if (!trackpair.first) {
				// getTrackTitle wants us to retry in a few ms...
				int interval = AntiscrollInterval;
				if (++antiscrollCounter_ > 10) {
					antiscrollCounter_ = 0;
					interval = NormInterval;
				}
				setInterval(interval);
				return Tune();
			}
			antiscrollCounter_ = 0;
			tune.setName(trackpair.second);
			tune.setURL(trackpair.second);
			tune.setTrack(QString::number(position + 1));
			tune.setTime(SendMessage(hWnd, WM_WA_IPC, 1, IPC_GETOUTPUTTIME));
		}
	}
	return tune;
}

Tune WinAmpTuneController::currentTune() const
{
	return prevTune_;
}
