var TPlayerInterface = function()
{
    // ## PUBLIC PROPERTIES

    /**
     * ID of the HTML element containing the track title label
     *
     * @field
     * @type <string>
     */
    this.trackLabelElementID = null;

    /**
     * ID of the HTML element containing the track title
     *
     * @field
     * @type <string>
     */
    this.trackElementID = null;

    /**
     * ID of the HTML element containing the track time label
     *
     * @field
     * @type <string>
     */
    this.trackTimeLabelElementID = null;

    /**
     * ID of the HTML element containing the track time
     *
     * @field
     * @type <string>
     */
    this.trackTimeElementID = null;

    /**
     * ID of the HTML element containing the artist label
     *
     * @field
     * @type <string>
     */
    this.artistLabelElementID = null;

    /**
     * ID of the HTML element containing the artist name
     *
     * @field
     * @type <string>
     */
    this.artistElementID = null;

    /**
     * ID of the HTML element containing the station name
     *
     * @field
     * @type <string>
     */
    this.stationNameElementID = null;

    /**
     * ID of the HTML element containing the favorite / unfavorite button
     *
     * @field
     * @type <string>
     */
    this.favoriteElementID = null;

    /**
     * ID of the HTML element containing the play / stop button
     *
     * @field
     * @type <string>
     */
    this.playStopElementID = null;

    /**
     * ID of the HTML element containing the toggle mute button
     *
     * @field
     * @type <string>
     */
    this.toggleMuteElementID = null;

    /**
     * ID of the HTML element containing the volume slider and its background
     *
     * @field
     * @type <string>
     */
    this.volumeSliderContainerElementID = null;

    /**
     * ID of the HTML element containing the volume slider itself
     *
     * @field
     * @type <string>
     */
    this.volumeSliderElementID = null;

    /**
     * The default volume level to return if we have not stored it yet (0 - 100)
     *
     * @field
     * @type <int>
     */
    this.defaultVolumeLevel = 50;

    /**
     * Prefix for the IDs of the preset anchor (link) tags.
     *
     * The presets should have IDs of [presetsPrefix][number], for example: PresetLink1
     *
     * @field
     * @type <string>
     */
    this.presetsPrefix = null;

    /**
     * The number of preset links supported in this configuration
     *
     * @field
     * @type <int>
     */
    this.presetCount = null;

    /**
     * Callback to accept station data in front end (for sharing scripts)
     *
     * @field
     * @type <function> TCallback(stationID, stationName)
     */
    this.stationDataCallback = null;

    // ## PUBLIC METHODS

    /**
     * Update the track title being displayed
     *
     * @param <string> trackName Title of the new track
     * @param <boolean> showLabel Should the label be shown (default true)
     * @return <void>
     */
    this.updateTrack = function(trackName, showLabel)
    {
	if (this.trackLabelElementID == null || this.trackElementID == null)
	{
	    Lint.log('TPlayerInterface::trackLabelElementID or TPlayerInterface::trackElementID not set');
	    return;
	}

	if (showLabel == null) showLabel = true;

	document.getElementById(this.trackLabelElementID).style.visibility =
	    (showLabel ? 'visible' : 'hidden');

	document.getElementById(this.trackElementID).innerHTML = trackName;
    }

    /**
     * Update the artist name being displayed
     *
     * @param <string> artistName Artist name
     * @param <boolean> showLabel Should the label be shown (default true)
     * @return <void>
     */

    this.updateArtist = function(artistName, showLabel)
    {
	if (this.artistLabelElementID == null || this.artistElementID == null)
	{
	    Lint.log('TPlayerInterface::artistLabelElementID or TPlayerInterface::artistElementID not set');
	    return;
	}

	if (showLabel == null) showLabel = true;

	document.getElementById(this.artistLabelElementID).style.visibility =
	    (showLabel ? 'visible' : 'hidden');

	document.getElementById(this.artistElementID).innerHTML = artistName;
    }

    /**
     * Update the station name being displayed
     *
     * @param <string> stationName Station name
     * @return <void>
     */
    this.updateStationName = function(stationName)
    {
	if (this.stationNameElementID == null)
	{
	    Lint.log('TPlayerInterface::stationNameElementID not set');
	    return;
	}

	document.getElementById(this.stationNameElementID).innerHTML = stationName;

	if (this.stationDataCallback != null)
	{
	    var c = playerWrapper.getPlayerController();
	    if (c != null)
		this.stationDataCallback(c.stationID, stationName);
	}
    }

    /**
     * Update the URL of the station logo image
     *
     * @param <string> imageURL URL to the new image
     * @return <void>
     */
    this.updateStationLogo = function(imageURL, stationID)
    {
	if (this.stationLogoElementID == null)
	{
	    Lint.log('TPlayerInterface::stationLogoElementID not set');
	    return;
	}

	var em = document.getElementById(this.stationLogoElementID);

	if (imageURL == null || imageURL == '')
	    em.style.visibility = 'hidden';
	else
	{
	    em.innerHTML = '<a href="/play/' + stationID + '/" border="0"><img title="Station info" src="' + imageURL + '" /></a>';
	    em.style.visibility = 'visible';
	}
    }

    /**
     * Update the track time being displayed
     *
     * @param <string> trackTime The new track time to display
     * @param <boolean> showLabel Should the label be shown (default true)
     * @return <void>
     */
    this.updateTrackTime = function(trackTime, showLabel)
    {
	if (this.trackTimeLabelElementID == null || this.trackTimeElementID == null)
	{
	    Lint.log('TPlayerInterface::trackTimeLabelElementID or TPlayerInterface::trackTimeElementID not set');
	    return;
	}

	if (showLabel == null) showLabel = true;

	document.getElementById(this.trackTimeLabelElementID).style.visibility =
	    (showLabel ? 'visible' : 'hidden');

	document.getElementById(this.trackTimeElementID).innerHTML = trackTime;
    }

    /**
     * Update the volume slider level
     *
     * @param <integer> level New volume level between 0 and 100
     * @return <void>
     */
    this.updateVolumeSlider = function(level)
    {
	lastVolume = level;

	if (this.volumeSliderElementID == null)
	{
	    Lint.log('TPlayerInterface::volumeSliderElementID not set');
	    return;
	}

	var em = document.getElementById(this.volumeSliderElementID);

	$(em).slider('option', 'value', level);
    }

    /**
     * Render the stop button
     *
     * @return <void>
     */
    this.renderStopButton = function()
    {
	if (!this.checkControlElements()) return false;

	var em = document.getElementById(this.playStopElementID);
	em.firstChild.href="javascript:playerWrapper.stop();";
	em.firstChild.firstChild.src = "http://media.audiorealm.com/images/player/stop.png";
    }

    /**
     * Render the play button
     *
     * @return <void>
     */
    this.renderPlayButton = function()
    {
	if (!this.checkControlElements()) return false;

	var em = document.getElementById(this.playStopElementID);
	em.firstChild.href="javascript:playerWrapper.play();";
	em.firstChild.firstChild.src = "http://media.audiorealm.com/images/player/play.png";
    }

    /**
     * Render the eject button
     *
     * @return <void>
     */
    this.renderEjectButton = function()
    {
	if (!this.checkControlElements()) return false;

	var em = document.getElementById(this.playStopElementID);
	em.firstChild.href="javascript:playerWrapper.eject();";
	em.firstChild.firstChild.src = "http://media.audiorealm.com/images/player/eject.png";
	em.style.visibility = 'visible'; // Override hidden-ness for this
    }

    /**
     * Render the mute button
     *
     * @return <void>
     */
    this.renderMuteButton = function()
    {
	if (!this.checkControlElements()) return false;

	var em = document.getElementById(this.toggleMuteElementID);
	em.firstChild.firstChild.src = "http://media.audiorealm.com/images/player/volume.png";
    }

    /**
     * Render the unmute button
     *
     * @return <void>
     */
    this.renderUnMuteButton = function()
    {
	if (!this.checkControlElements()) return false;

	var em = document.getElementById(this.toggleMuteElementID);
	em.firstChild.firstChild.src = "http://media.audiorealm.com/images/player/mute.png";
    }

    /**
     * Hide all controls
     *
     * @return <void>
     */
    this.hideControls = function()
    {
	if (!this.checkControlElements()) return false;

	document.getElementById(this.favoriteElementID).style.visibility =
	    document.getElementById(this.toggleMuteElementID).style.visibility =
	    document.getElementById(this.playStopElementID).style.visibility =
	    document.getElementById(this.volumeSliderContainerElementID).style.visibility = 'hidden';
    }

    /**
     * Show all controls
     *
     * @return <void>
     */
    this.showControls = function()
    {
	if (!this.checkControlElements()) return;

	document.getElementById(this.favoriteElementID).style.visibility =
	    document.getElementById(this.toggleMuteElementID).style.visibility =
	    document.getElementById(this.playStopElementID).style.visibility =
	    document.getElementById(this.volumeSliderContainerElementID).style.visibility = 'visible';
    }

    /**
     * Show the favorite button (even if other controls remain hidden)
     *
     * @return <void>
     */
    this.showFavoriteButton = function()
    {
	if (!this.checkControlElements()) return;

	var em = document.getElementById(this.favoriteElementID);
	em.style.visibility = 'visible';
    }

    /**
     * Used by the hidden player to ask us for the last volume we remember
     *
     * @return <int>
     */
    this.recallVolume = function()
    {
	var defaultLevel = this.defaultVolumeLevel;

	var l = this.getCookie('arVolume');
	if (l != null) defaultLevel = l;

	var v = (lastVolume == null ? defaultLevel : lastVolume);
	Lint.log("TPlayerInterface::recallVolume: Sending level " + v);
	return v;
    }

    /**
     * Update inteface elements that must change if user has logged in
     *
     * @return <void>
     */
    this.userLoggedIn = function()
    {
	loggedInUser = true;
	if (!this.checkControlElements()) return;
	Lint.log("TPlayerInterface::userLoggedIn: Updating interface");
	this.initPresets();
	this.refreshFavorite();
    }

    /**
     * Update inteface elements that must change if user has logged out
     *
     * @return <void>
     */
    this.userLoggedOut = function()
    {
	loggedInUser = false;
	if (!this.checkControlElements()) return;
	Lint.log("TPlayerInterface::userLoggedOut: Updating interface");
	this.initPresets();
	this.setPresets(null);
	this.refreshFavorite();
    }

    /**
     * Set the user presets
     *
     * @param <array> presets Array containing the user's presets
     * @return <void>
     */
    this.setPresets = function(presets)
    {
	if (!this.checkControlElements()) return;

	if (presets == null)
	    presets = {'1':null,'2':null,'3':null,'4':null,'5':null,'6':null};

	var em = null;
	var idx = null;

	for (var i = 1; i <= this.presetCount; i++)
	{
	    idx = i.toString();
	    em = document.getElementById(this.presetsPrefix + idx);
	    if (presets[idx] != null)
	    {
		em.className = 'enabled';
		em.onclick = function() {playerWrapper.selectStation($(this).data('stationID'));return false;}
		$(em).data('stationID', presets[idx]);
		$('div', em.parentNode).html(
		    "<a href='#' onclick='playerWrapper.selectStation(" + presets[idx] + "); return false;'>Tune to station</a> " +
		    "<a href='#' onclick='playerWrapper.setPreset(" + idx + "); return false'>Set to current</a>");
	    }
	    else
	    {
		em.className = '';
		em.onclick = function() {playerWrapper.setPreset($(this).data('idx'));return false;}
		$(em).data('idx', idx);
		if (loggedInUser) $('div', em.parentNode).html("<a href='#' onclick='playerWrapper.setPreset(" + idx + "); return false;'>Set to current</a>");
	    }
	}
    }

    /**
     * Refresh the user's presets (after updating favorites, login etc)
     *
     * @return <void>
     */
    this.refreshPresets = function()
    {
	$.ajax({
	    url: '/user/getpresets/format/json',
	    type: 'GET',
	    dataType: 'json',
	    success: function(data)
	    {
		playerInterface.setPresets(data.presets);
	    }
	});
    }

    /**
     * Refresh the station's favorite status
     *
     * @return <void>
     */
    this.refreshFavorite = function()
    {
	var c = playerWrapper.getPlayerController();
	if (c != null)
	{
	    var current = c.stationID;
	    if (current != 0)
	    {
		$.ajax({
		    url: '/user/isfavorite/format/json',
		    type: 'POST',
		    data: {stationID:current},
		    dataType: 'json',
		    success: function(data)
		    {
			playerInterface.setFavorite(data.isFavorite);
		    }
		});
	    }
	}
    }

    //## PRIVATE VARIABLES
    var lastVolume = null;
    var loggedInUser = false;
    var presetsReady = false;

    // ## PRIVATE METHODS

    /**
     * Check if the control element IDs have been correctly set
     *
     * @return <boolean>
     */
    this.checkControlElements = function()
    {
	if (this.playStopElementID == null)
	{
	    Lint.log("TPlayerInterface::playStopElementID not set");
	    return false;
	}

	if (this.favoriteElementID == null)
	{
	    Lint.log("TPlayerInterface::favoriteElementID not set");
	    return false;
	}

	if (this.toggleMuteElementID == null)
	{
	    Lint.log("TPlayerInterface::toggleMuteElementID not set");
	    return false;
	}

	if (this.volumeSliderContainerElementID == null)
	{
	    Lint.log("TPlayerInterface::volumeSliderContainerElementID not set");
	    return false;
	}

	if (this.presetsPrefix == null)
	{
	    Lint.log("TPlayerInterface::presetsPrefix not set");
	    return false;
	}

	if (this.presetCount == null)
	{
	    Lint.log("TPlayerInterface::presetCount not set");
	    return false;
	}

	return true;
    }

    /**
     * Set up the favorite status of the player
     *
     * @param <boolean> isFavorite Is this station a favorite?
     * @return <void>
     */
    this.setFavorite = function(isFavorite)
    {
	if (!loggedInUser) return;

	if (!this.checkControlElements()) return;

	var em = document.getElementById(this.favoriteElementID);

	Lint.log("TPlayerInterface::setFavorite - Setting favorite status");

	var oldURL = '';
	var imageURL = '';

	if (isFavorite)
	{
	    em.firstChild.onclick =function() {playerWrapper.removeFavorite();return false;}
	    oldURL = em.firstChild.firstChild.src;
	    imageURL = oldURL.substr(0, oldURL.indexOf('fav'));
	    em.firstChild.firstChild.src = imageURL + 'fav_selected.png';
	    $(em.firstChild.firstChild).attr('original-title','Remove from favorites');
	}
	else
	{
	    em.firstChild.onclick = function() {playerWrapper.addFavorite();return false;}
	    oldURL = em.firstChild.firstChild.src;
	    imageURL = oldURL.substr(0, oldURL.indexOf('fav'));
	    em.firstChild.firstChild.src = imageURL + 'fav.png';
	    $(em.firstChild.firstChild).attr('original-title','Add to favorites');
	}
    }

    /**
     * Initialize the presets (only run once)
     *
     * @return <void>
     */
    this.initPresets = function()
    {
	if (presetsReady) return;
	presetsReady = true;
	if (!this.checkControlElements()) return;
	Lint.log("TPlayerInterface::initPresets: Initializing presets");
	var em = null;
	if (loggedInUser) for (var i = 1; i <= this.presetCount; i++)
	{
	    em = document.getElementById(this.presetsPrefix + i);

	    $(em.parentNode).hoverIntent({
		sensitivity: 3,
		interval: 500,
		over: function() {$("div", this).css('display', 'block');},
		out: function() {$("div", this).css('display', 'none');}
		});

	    em = document.getElementById(this.favoriteElementID);
	    $(em).attr('original-title','Add to favorites');
	    $(em).tipsy({gravity:'w',fade:true,title: function() {return (this.firstChild.firstChild.src.indexOf('selected') != -1 ? 'Remove from favorites' : 'Add to favorites');}});
	}
	else
	{
	    em = document.getElementById(this.presetsPrefix + '1').parentNode.parentNode;
	    em.title = 'Please register and log in to enable station presets.';
	    $(em).tipsy({gravity:'w',fade:true});

	    em = document.getElementById(this.favoriteElementID);
	    em.title = 'Please register and log in to enable favorite stations.';
	    $(em).tipsy({gravity:'w',fade:true});
	}
    }

    this.getCookie = function(c_name)
    {
	if (document.cookie.length>0)
	{
	    var c_start=document.cookie.indexOf(c_name + "=");

	    if (c_start!=-1)
	    {
		c_start=c_start + c_name.length+1;
		var c_end=document.cookie.indexOf(";",c_start);
		if (c_end==-1) c_end=document.cookie.length;
		return unescape(document.cookie.substring(c_start,c_end));
	    }
	}
	return null;
    }
}
