function log(msg) { };

var swfEventDidFire = function(eventName, param) {
	if (window.master) {
		window.master._swfEventDidFire(eventName, param);
	}
};

var Player = {};

Player.Request = Class.create(Ajax.Request, {
	initialize: function($super, url, options) {
		options = Object.extend({
			method:'get',
			requestHeaders:{Accept:'application/json'}
		}, options || {});
		$super(url, options);
	}
});

Player.ratings = [
	{rating:-3, adjective:'terrible',    cls:'down'},
	{rating:-2, adjective:'bad',         cls:'down'},
	{rating:-1, adjective:'not so good', cls:'down'},
	{rating:1,  adjective:'good',        cls:'up'},
	{rating:2,  adjective:'great',       cls:'up'},
	{rating:3,  adjective:'favorite',    cls:'way-up'},
];

Player.User = Class.create({
	initialize: function(initialProperties) {
		Object.extend(this, initialProperties || {});
	}
});

Player.Track = Class.create({
	initialize: function(initialProperties) {
		Object.extend(this, initialProperties || {});
		if (this.artist) {
			this.artist = new Player.User(this.artist);
		}
		this.rating = null;
	},

	requestRating: function(handler) {
		if (this.rating) {
			handler(this);
		} else {
			new Player.Track.RatingRequest(this, null, handler);
		}
	},

	setRating: function(rating, handler) {
		new Player.Track.RatingRequest(this, rating, handler);
	}
});

Player.Track.RatingRequest = Class.create(Player.Request, {
	initialize: function($super, track, rating, handler) {
		this._track = track;
		this._handler = handler;
		options = {
			parameters:{track:track.key},
			onComplete:this._didReceiveResponse.bind(this)
		};
		if (rating) {
			options.method = 'post',
			options.parameters.rating = rating
		}
		$super('/player/rating', options);
	},

	_didReceiveResponse: function(response) {
		this._track.rating = response.responseJSON.rating;
		this._handler(this._track);
	}
});

Player.Track.Cache = new Hash();
Player.Track.Request = Class.create(Player.Request, {
	initialize: function($super, key, handler) {
		var track = Player.Track.Cache.get(key);
		if (track) {
			log('Player.Track: cache hit: ' + key);
			if (handler) {handler(track);}
		} else {
			log('Player.Track: cache miss: ' + key);
			this._handler = handler;
			$super(
				'/player/track',
				{
					parameters: {track:key},
					onComplete: this._didReceiveResponse.bind(this)
				}
			);
		}
	},

	_didReceiveResponse: function(response) {
		var track = new Player.Track(response.responseJSON);
		log('Player.Track: cache set: ' + track.key);
		Player.Track.Cache.set(track.key, track);
		if (this._handler) {this._handler(track);}
	}
});

Player.Radio = Class.create({
	initialize: function(initialProperties) {
		Object.extend(this, initialProperties || {});
	},

	requestTrack: function(handler) {
		new Player.Radio.TrackRequest(this, handler);
	}
});

Player.Radio.TrackRequest = Class.create(Player.Request, {
	initialize: function($super, radio, handler) {
		this._handler = handler;
		$super('/player/radio', {
				parameters:(radio.channel ? {channel:radio.channel} : {owner:radio.owner}),
				onComplete:this._didReceiveResponse.bind(this)
		});
	},

	_didReceiveResponse: function(response) {
		var keys = response.responseJSON.keys;
		new Player.Track.Request(keys[0], this._handler);
	}
});

Player.Playlist = Class.create({
	initialize: function(initialProperties) {
		Object.extend(this, initialProperties || {});
		if (!this.keys) {
			this.keys = new Array(this.count);
			this.playlistType = 'playlist';
		} else {
			this.count = this.keys.length;
			this.playlistType = 'collection';
		}
	},

	requestTrack: function(index, handler) {
		var key = this.keys[index];
		if (key) {
			new Player.Track.Request(key, handler);
		} else {
			new Player.Playlist.TracksRequest(this, index, handler);
		}
	},

	_gotTracks: function(response, index, handler) {
		log('Player.Playlist._gotTracks');
		var i;
		for (i = 0; i < response.keys.length; i++) {
			this.keys[i + response.offset] = response.keys[i];
		}
		var key = this.keys[index];
		new Player.Track.Request(key, handler);
	}
});

Player.Playlist.chunkSize = 10;

Player.Playlist.Cache = new Hash();
Player.Playlist.Request = Class.create(Player.Request, {
	initialize: function($super, key, handler) {
		var playlist = Player.Playlist.Cache.get(key);
		if (playlist) {
			log('Player.Playlist: cache hit: ' + key);
			if (handler) {handler(playlist);}
		} else {
			log('Player.Playlist: cache miss: ' + key);
			this._handler = handler;
			$super(
				'/player/playlist',
				{
					parameters: {playlist:key},
					onComplete: this._didReceiveResponse.bind(this)
				}
			);
		}
	},

	_didReceiveResponse: function(response) {
		var playlist = new Player.Playlist(response.responseJSON);
		log('Player.Playlist: cache set: ' + playlist.key);
		Player.Playlist.Cache.set(playlist.key, playlist);
		if (this._handler) {this._handler(playlist);}
	}
});

Player.Playlist.TracksRequest = Class.create(Player.Request, {
	initialize: function($super, playlist, index, handler) {
		this._playlist = playlist;
		this._index = index;
		this._handler = handler;
		$super(
			'/player/tracks',
			{
				parameters: {
					playlist: playlist.key,
					offset: Math.floor(index / Player.Playlist.chunkSize) * Player.Playlist.chunkSize,
					limit: Player.Playlist.chunkSize
				},
				onComplete: this._didReceiveResponse.bind(this)
			}
		);
	},

	_didReceiveResponse: function(response) {
		this._playlist._gotTracks(response.responseJSON, this._index, this._handler);
	}
});

Player.Master = Class.create({
	initialize: function(element, remote) {
		this._element = element;
		this._playing = false;
		this._playedToEnd = false;
		this._ready = false;
		this._duration = 0;
		this._progress = 0;
		this._playstart = 0;
		this._playtime = 0;
		this._player_tracking_id = ('' + Math.random(100000)).substr(5,12);
		this._sequence_index = 0;
		this._buildSWF('player-master-swf');

		this._volume = Cookie.get('player-volume');
		if (!this._volume) {
			this._volume = 1.0;
			Cookie.set('player-volume', this._volume);
		}

		this._resetPlayState();

		this._inlineRemote = remote;
		this._openerRemote = window.opener.remote;
		window.master = this;
		Cookie.set('playerOpen', 'true');
		Event.observe(window, 'beforeunload', this._windowWillClose.bind(this));
	},

	currentPlaylist: function() {
		return this._current.playlist;
	},

	currentTrack: function() {
		return this._current.track;
	},

	playing: function() {
		return this._playing;
	},

	duration: function() {
		return this._duration;
	},

	progress: function() {
		return this._progress;
	},

	playtime: function() {
		var pt = this._playtime;
		if (this._playstart != 0) {
			pt += (new Date().getTime()) - this._playstart;
		}
		return pt;
	},

	volume: function() {
		return this._volume;
	},

	setVolume: function(volume) {
		if (volume < 0) {volume = 0;}
		if (volume > 1) {volume = 1;}
		log('master: setVolume: ' + volume);
		this._volume = volume;
		this.swf().setVolume(volume);
		Cookie.set('player-volume', volume);
		this.fire('player:stateDidChange');
	},

	enable: function() {
		if (this.disabledMessage) {
			this.disabledMessage = null;
			if (this._playOnEnable) {
				this.play();
				this._playOnEnable = false;
			}
			this.fire('player:stateDidChange');
		}
	},

	disable: function(message) {
		this.disabledMessage = message;
		if (this.playing()) {
			this.pause();
			this._playOnEnable = true;
		} else {
			this._playOnEnable = false;
		}
		this.fire('player:stateDidChange');
	},

	play: function(playOptions) {
		if (!playOptions) {
			log('master: play');
			if (this.swf()) {
				this.swf().doPlay();
			}
		} else {
			this._resetPlayState();
			this._progress = 0;
			this._playedToEnd = false;
			if (playOptions.srcUrl != '') {
			  this._srcUrl = playOptions.srcUrl;
			}
			this.fire('player:stateDidChange');
			if (playOptions.track) {
				new Player.Track.Request(playOptions.track, this._playTrack.bind(this));
			}
			else if (playOptions.playlist) {
				this._current.index = playOptions.index ? playOptions.index : 0;
				new Player.Playlist.Request(playOptions.playlist, this._playPlaylist.bind(this));
			}
			else if (playOptions.tracks) {
				this._current.index = playOptions.index ? playOptions.index : 0;
				this._current.playlist = new Player.Playlist(playOptions.tracks);
				this._current.playlist.requestTrack(this._current.index, this._playTrack.bind(this));
			}
			else if (playOptions.radio) {
				this._current.radio = new Player.Radio(playOptions.radio);
				this._current.radio.requestTrack(this._playTrack.bind(this));
			}
		}
	},

	pause: function() {
		log('master: pause');
		this.swf().doPause();
	},

	seek: function(seconds) {
		log('master: seek ' + seconds);
		this._progress = seconds;
		this.fire('player:progressDidChange');
		this.swf().seek(seconds);
	},

	sendTracking: function(async) {
		var play_seconds = Math.floor(this.playtime() / 1000);
		if (play_seconds > 1) {
			var trackingUrl = '';
			if (this._tracking && this._tracking.track) {
				trackingUrl = this._tracking.track.tracking_url;
			}
			else {
				log('master: sendTracking NO current track!');
			}
			
			if (trackingUrl == '') {
				log('master: sendTracking NO tracking url!');
				return;
			}

			trackingUrl = trackingUrl.replace(/PLAYER_ID/g, this._player_tracking_id);
			trackingUrl = trackingUrl.replace(/SEQUENCE_INDEX/g, this._sequence_index++);
			trackingUrl = trackingUrl.replace(/DURATION/g, play_seconds);
			
			if (this._tracking.radio) {
				log('master: tracking the radio')
				trackingUrl = trackingUrl.replace(/PLAYLIST_TYPE/g, 'radio-' + this._tracking.radio.source_type);
				trackingUrl += '&playlist_key=' + this._tracking.radio.source_name;
			}
			else if (this._tracking.playlist) {
				log('master: tracking a playlist')
				trackingUrl = trackingUrl.replace(/PLAYLIST_TYPE/g, this._tracking.playlist.playlistType);
				trackingUrl += '&playlist_key=' + this._tracking.playlist.key;
			}
			else {
				log('master: tracking a track')
				trackingUrl = trackingUrl.replace(/PLAYLIST_TYPE/g, 'single-item');
			}
			log('master: about to send google tracking sendTracking url: ' + trackingUrl);

			try {
				var gaTracker = _gat._getTracker("UA-990912-1");
				gaTracker._initData();
				gaTracker._trackPageview(trackingUrl);
	    } catch(err) { log('Error calling gaTracker: ' + err);}
			log('master: sendTracking url: ' + trackingUrl);
			new Ajax.Request(trackingUrl, {parameters:{source_url:this._srcUrl}, asynchronous:async});
		}
		this._playtime = 0;
		this._playstart = this.playing() ? (new Date().getTime()) : 0;
	},

	previousTrack: function() {
		log('master: previousTrack');
		if (this.isPreviousTrackEnabled()) {
			if (this._progress > 3) {
				this.seek(0);
			} else {
				this._current.index = (this._current.index + this._current.playlist.count - 1) % this._current.playlist.count;
				this._current.playlist.requestTrack(this._current.index, this._playTrack.bind(this));
			}
		}
	},

	nextTrack: function() {
		log('master: nextTrack');
		if (this.isNextTrackEnabled()) {
			if (this._current.playlist) {
				this._current.index = (this._current.index + 1) % this._current.playlist.count;
				this._current.playlist.requestTrack(this._current.index, this._playTrack.bind(this));
			}
			else if (this._current.radio) {
				this._current.radio.requestTrack(this._playTrack.bind(this));
			}
		}
	},

	isPreviousTrackEnabled: function() {
		if (this._current.playlist) {
			return this._current.index > 0;
		}
		else {
			return false
		}
	},

	isNextTrackEnabled: function() {
		if (this._current.playlist) {
			return this._current.index < (this._current.playlist.count - 1);
		}
		else if (this._current.radio) {
			return true;
		}
		else {
			return false;
		}
	},

	observe: function(eventName, handler) {
		this._element.observe(eventName, handler);
	},

	stopObserving: function(eventName, handler) {
		this._element.stopObserving(eventName, handler);
	},

	fire: function(eventName) {
		this._element.fire(eventName);
	},

	swf: function() {
		return $('player-master-swf');
	},

	_swfEventDidFire: function(eventName, param) {
		// log('master: swf event: ' + eventName + ', ' + param);
		if (eventName == 'player:play') {
			if (this._playstart == 0) {
				this._playstart = new Date().getTime();
			}
			this._playing = true;
			this._playedToEnd = false;
			this.fire('player:stateDidChange');
		} else if (eventName == 'player:pause') {
			if (this._playstart != 0) {
				this._playtime += (new Date().getTime()) - this._playstart;
				this._playstart = 0;
			}
			this._playing = false;
			this.fire('player:stateDidChange');
		} else if (eventName == 'player:ready') {
			this._ready = true;
			this.setVolume(this._volume);
			if (this._inlineRemote) {
				log('master: connecting inline remote');
				this._inlineRemote.connect(this);
			}
			if (this._openerRemote) {
				log('master: connecting opener remote');
				this._openerRemote.connect(this);
			}
		} else if (eventName == 'player:duration') {
			this._duration = Math.floor(param);
			this.fire('player:progressDidChange');
		} else if (eventName == 'player:progress') {
			this._progress = Math.floor(param);
			this.fire('player:progressDidChange');
			if (this._playing && this._progress == this._duration) 
				this._playedToEnd = true;
		} else if (eventName == 'player:netStatus' && param == 'NetStream.Play.Stop' && this._playedToEnd) {
			log("master: played to end");
			this.nextTrack();
		}

		// this.fire(eventName);
	},

	_resetPlayState: function() {
		this._current = {
			track: null,
			playlist: null,
			radio: null,
			index: 0
		}
	},

	_windowWillClose: function() {
		this.sendTracking(false);
		Cookie.erase('playerOpen');
		this.fire('player:willClose');
	},

	_playTrack: function(track) {
		this.sendTracking(true);
		this._current.track = track;
		this._progress = 0;
		this._tracking = this._current;
		this.swf().playTrack(this._current.track.media_url);
		this.fire('player:trackDidChange');
	},

	_playPlaylist: function(playlist) {
		this._current.playlist = playlist;
		this._current.playlist.requestTrack(this._current.index, this._playTrack.bind(this));
	},

	_buildSWF: function(eltID) {
		var elt = new Element('div', {id:eltID});
		this._element.appendChild(elt);
		swfobject.embedSWF(
			'/flash/remote_player.swf',
			eltID,
			1, 1,
			String('9,0,0,0'),
			'/flash/remote_player',
			{}, {},
			{id:eltID, name:eltID}
		);
	}
});

Player.Button = Class.create({
	initialize: function(link, handler) {
		this._link = link;
		this._handler = handler;

		this._link.onclick = function() {return false;}
		this._link.observe('click', this._doCommand.bind(this));
	},

	show: function() {this._link.show();},
	hide: function() {this._link.hide();},
	enable: function() {this.setEnabled(true);},
	disable: function() {this.setEnabled(false);},
	setEnabled: function(enabled) {
		if (enabled) {
			this._link.removeClassName('disabled');
		} else {
			this._link.addClassName('disabled');
		}
	},

	_doCommand: function() {
		if (!this._link.hasClassName('disabled')) {
			this._handler.call();
		}
	}
});

Player.Scrubber = Class.create({
	initialize: function(element, handler) {
		this._duration = 0;
		this._progress = 0;
		this._downloadProgress = 0;
		this._handler = handler;
		this._dragging = false;

		this._track = new Element('div');
		this._track.addClassName('track');
		this._track.setStyle({width:'100%'});
		element.appendChild(this._track);

		this._downloadBar = new Element('div');
		this._downloadBar.addClassName('download-bar');
		this._downloadBar.setStyle({width:'0px'});
		this._track.appendChild(this._downloadBar);

		this._playBar = new Element('div');
		this._playBar.addClassName('play-bar');
		this._playBar.setStyle({width:'0px'});
		this._track.appendChild(this._playBar);

		this._track.observe('mousedown', this._mouseDown.bindAsEventListener(this));
		document.observe('mousemove', this._mouseMoved.bindAsEventListener(this));
		document.observe('mouseup', this._mouseUp.bindAsEventListener(this));
	},

	setTimes: function(progress, duration) {
		this._progress = progress;
		this._duration = duration;
		this._updateScrubber();
	},

	_scrubForEvent: function(event) {
		var mw = this._track.getWidth();
		var w = event.pointerX() - this._track.cumulativeOffset()[0];
		if (w < 0) {w = 0;}
		if (w > mw) {w = mw;}
		this._playBar.setStyle({width:w + 'px'});

		if (this._handler) {
			var time = this._duration * w / mw;
			this._handler(time);
		}
	},

	_mouseDown: function(event) {
		this._dragging = true;
		this._scrubForEvent(event);
		event.stop();
	},

	_mouseMoved: function(event) {
		if (!this._dragging) {return;}
		this._scrubForEvent(event);
		event.stop();
	},

	_mouseUp: function(event) {
		if (!this._dragging) {return;}
		this._dragging = false;
		event.stop();
	},

	_updateScrubber: function() {
		var barWidth = this._track.getWidth();
		var downloadWidth = Math.floor(this._downloadProgress * barWidth);
		var playWidth = 0;
		if (this._duration != 0) {
			playWidth = Math.floor(barWidth * this._progress / this._duration);
		}
		this._downloadBar.setStyle({width:downloadWidth + 'px'});
		this._playBar.setStyle({width:playWidth + 'px'});
	}
});

Player.VolumeSlider = Class.create({
	initialize: function(element, handler) {
		this._element = element;
		this._track = new Element('div');
		this._track.addClassName('track');
		this._element.appendChild(this._track);
		this._value = 0;
		this._dragging = false;
		this._handler = handler;

		this._bar = new Element('div');
		this._bar.addClassName('bar');
		this._bar.setStyle({width:'0px'});
		this._track.appendChild(this._bar);

		this._updateBar();

		this._track.observe('mousedown', this._mouseDown.bindAsEventListener(this));
		document.observe('mousemove', this._mouseMoved.bindAsEventListener(this));
		document.observe('mouseup', this._mouseUp.bindAsEventListener(this));
	},

	value: function() {
		return this._value;
	},

	setValue: function(value) {
		if (value < 0) value = 0;
		if (value > 1) value = 1;
		this._value = value;
		this._updateBar();
	},

	enable: function() {this.setEnabled(true);},
	disable: function() {this.setEnabled(false);},
	setEnabled: function(enabled) {
		if (enabled) {
			this._bar.removeClassName('disabled');
		} else {
			this._bar.addClassName('disabled');
		}
	},

	_scrubForEvent: function(event) {
		var mw = this._track.getWidth();
		var w = event.pointerX() - this._track.cumulativeOffset()[0];
		if (w < 0) {w = 0;}
		if (w > mw) {w = mw;}
		this.setValue(w / mw);
		if (this._handler) {
			this._handler(this.value());
		}
	},

	_mouseDown: function(event) {
		if (this._bar.hasClassName('disabled')) {return;}
		this._track.setStyle({cursor:'pointer'});
		this._dragging = true;
		this._scrubForEvent(event);
		event.stop();
	},

	_mouseMoved: function(event) {
		if (!this._dragging) {return;}
		this._scrubForEvent(event);
		event.stop();
	},

	_mouseUp: function(event) {
		if (!this._dragging) {return;}
		this._dragging = false;
		event.stop();
	},

	_updateBar: function() {
		var w = Math.floor(this._track.getWidth() * this._value);
		this._bar.setStyle({width:w + 'px'});
	}
});

Player.Rater = Class.create({
	initialize: function(element) {
		this._element = $(element);
		this._thumbs = new Array(6);

		var lbl, ul, i;
		lbl = new Element('div');
		lbl.innerHTML = 'Rating:';
		ul = new Element('ul');

		for (i = 0; i < 6; i++)
		{
			var rtg = Player.ratings[i];
			var li = new Element('li');
			var a = new Element('a');

			a.addClassName(rtg.cls);
			a.innerHTML = '<span>' + rtg.adjective + '</span>';
			a.rating = rtg.rating;
			a.onclick = function() {return false;};
			a.observe('click', this.rate.bind(this));

			li.appendChild(a);
			ul.appendChild(li);

			this._thumbs[i] = a;
		}
		this._element.appendChild(lbl);
		this._element.appendChild(ul);

		this._gotRatingBound = this._gotRating.bind(this);

		this.setTrack(null);
	},

	rate: function(event) {
		var lnk = event.element();
		if (lnk && lnk.rating && this._track) {
			this._track.setRating(lnk.rating, this._gotRatingBound);
		}
	},

	setTrack: function(track) {
		if ((track != this._track) && track) {
		 	track.requestRating(this._gotRatingBound);	
		}
		else {
			this._element.hide();
		}
	},

	_gotRating: function(track) {
		log('Rater._gotRating: ' + track.key + ', ' + track.rating);
		this._track = track;
		if ((track.rating >= -3 && track.rating <= 3) && this._track) {
			this._thumbs.invoke('removeClassName', 'disabled');
			this._setLinkChecked(this._thumbs[0], (this._track.rating <= -3));
			this._setLinkChecked(this._thumbs[1], (this._track.rating <= -2));
			this._setLinkChecked(this._thumbs[2], (this._track.rating <= -1));
			this._setLinkChecked(this._thumbs[3], (this._track.rating >= 1));
			this._setLinkChecked(this._thumbs[4], (this._track.rating >= 2));
			this._setLinkChecked(this._thumbs[5], (this._track.rating >= 3));
			this._element.show();
		} else {
			this._element.hide();
		}
	},

	_setLinkChecked: function(lnk, checked) {
		if (checked) {
			lnk.addClassName('checked');
		} else {
			lnk.removeClassName('checked');
		}
	}
});

Player.Remote = Class.create({
	initialize: function(element) {
		this._element = element;
		this._master = null;
		this._shuttingDown = false;
		this._trackToPlay = null;
		this._windowID = 'ourstage_player';
		this._windowParams = 'width=446,height=160,scrollbars=no,resizable=no,status=no,location=no,menubar=no';
		this._display = this._element.down('.display');
		this._message = this._element.down('.message');
		this._trackInfo = this._element.down('.track-info');
		this._basePlayerDiv = this._element.up('#our-player-bar');
		this._trackInfoTemplate = this._trackInfo.innerHTML;
	
		this._stateDidChangeBound = this._stateDidChange.bind(this);
		this._progressDidChangeBound = this._progressDidChange.bind(this);
		this._playerWillCloseBound = this._playerWillClose.bind(this);
		this._trackDidChangeBound = this._trackDidChange.bind(this);

		this._playButton = new Player.Button(this._element.down('a.play'), this.play.bind(this));
		this._pauseButton = new Player.Button(this._element.down('a.pause'), this.pause.bind(this));
		this._prevButton = new Player.Button(this._element.down('a.prev'), this.previousTrack.bind(this));
		this._nextButton = new Player.Button(this._element.down('a.next'), this.nextTrack.bind(this));
		this._scrubber = new Player.Scrubber(this._element.down('.scrubber'), this.seek.bind(this));
		this._volumeSlider = new Player.VolumeSlider(this._element.down('div.volume'), this.setVolume.bind(this));
		var raterElt = this._element.down('div.rating');
		if (raterElt) {
			this._rater = new Player.Rater(raterElt);
		}

		this._updateUI();
		
		window.remote = this;
		
		Event.observe(window, 'beforeunload', this._windowWillClose.bind(this));
		if (Player.trackChangeFunction) {this.observe('player:trackDidChange', Player.trackChangeFunction);}
		if (!$('player-master')) {
			this._findMaster();
			this.defaultDisplay();
		}
		
	},

	observe: function(eventName, handler) {
		this._element.observe(eventName, handler);
	},

	stopObserving: function(eventName, handler) {
		this._element.stopObserving(eventName, handler);
	},

	fire: function(eventName) {
		this._element.fire(eventName);
	},

	playlistDidChange: function(playlistKey) {
	},

	currentTrack: function() {
		return this._master ? this._master.currentTrack() : null;
	},

	disabledMessage: function() {
		return this._master ? this._master.disabledMessage : null;
	},

	initialMessage: function() {
		if (this._master) {
			this._initialMessage = null;
		}
		return this._initialMessage;
	},

	enable: function(message) {
		this._initialMessage = message;
		if (this._master) {
			this._master.enable();
		}
		if (this.initialMessage() && this._basePlayerDiv.getHeight() < this._originalPlayerHeight) {
			this._basePlayerDiv.setStyle({height: this._originalPlayerHeight + 'px'});
			if (window.ourResizer) window.ourResizer.measureLayout();	
		}		
		this._updateUI();
	},

	disable: function(message) {
		if (this._master) {
			this._master.disable(message);
		} else {
			this._toDisableMessage = message;
		}
	},
	
	defaultDisplay: function() {
		// a default display for the player.. lets hide it initially
		if (!this._master) {
			this._originalPlayerHeight = this._basePlayerDiv.getHeight();
			this._basePlayerDiv.setStyle({height:'0'});
			if (window.ourResizer) window.ourResizer.measureLayout();
		}
	},

	play: function(playOptions) {
		if (!playOptions) {
			if (this._master) {this._master.play();}
		} else {
			this._showMaster();
			if (this._master) {
				this._master.play(playOptions);
			} else {
				this._toPlayOptions = playOptions;
			}
		}
	},

	pause: function() {if (this._master) {this._master.pause();}},
	previousTrack: function() {if (this._master) {this._master.previousTrack();}},
	nextTrack: function() {if (this._master) {this._master.nextTrack();}},
	setVolume: function(volume) {if (this._master) {this._master.setVolume(volume);}},
	seek: function(seconds) {if (this._master) {this._master.seek(seconds);}},

	connect: function(master) {
		if (this._shuttingDown) {return;}
		if (!this._master) {
			log('remote: connecting');
			this._master = master;
			this._master.observe('player:stateDidChange', this._stateDidChangeBound);
			this._master.observe('player:progressDidChange', this._progressDidChangeBound);
			this._master.observe('player:willClose', this._playerWillCloseBound);
			this._master.observe('player:trackDidChange', this._trackDidChangeBound);
			if (this._toPlayOptions) {
				this._master.play(this._toPlayOptions);
				this._toPlayOptions = null;
			}
			this._initialMessage = null;
			if (this._toDisableMessage) {
				this._master.disable(this._toDisableMessage);
				this._toDisableMessage = null;
			} else {
				this._master.enable();
			}
			this._updateUI();
		}
	},

	disconnect: function() {
		if (this._master) {
			log('remote: disconnecting');
			this._master.stopObserving('player:stateDidChange', this._stateDidChangeBound);
			this._master.stopObserving('player:progressDidChange', this._progressDidChangeBound);
			this._master.stopObserving('player:willClose', this._playerWillCloseBound);
			this._master.stopObserving('player:trackDidChange', this._trackDidChangeBound);
			this._master = null;
			this._updateUI();
		}
	},

	_trackDidChange: function() {
		log('remote: trackDidChange');
		this.fire('player:trackDidChange');
	},

	_stateDidChange: function() {
		log('remote: stateDidChange');
		this._updateUI();
	},

	_progressDidChange: function() {
		// log('remote: progressDidChange');
		this._updateScrubber();
	},

	_playerWillClose: function() {
		log('remote: playerWillClose');
		this.disconnect();
	},

	_windowWillClose: function() {
		log('remote: windowWillClose');
		this._shuttingDown = true;
		this.disconnect();
	},

	_updateUI: function() {
		this._updateControls();
		this._updateDisplay();
	},

	_updateScrubber: function() {
		var p = 0;
		var d = 0;
		if (this._master) {
			p = this._master.progress();
			d = this._master.duration();
		}
		this._scrubber.setTimes(p, d);
		this._element.down('div.times').innerHTML = this._minSecStr(p) + ' / ' + this._minSecStr(d);
	},

	_minSecStr: function(time) {
		var minutes = new String(Math.floor(time / 60));
		var seconds = new String(Math.floor(time % 60));
		if (seconds.length == 1) {seconds = '0' + seconds;}
		return (minutes + ':' + seconds);
	},

	_updateDisplay: function() {
		var disableMessage = this.disabledMessage();
		var initialMessage = this.initialMessage();
		if (!this._master) {
			this._display.hide();
			if (this._rater) {this._rater.setTrack(null);}
		} else {
			var track = this.currentTrack();
			if (this._rater) {this._rater.setTrack(track);}
			if (track) {
				var trackTitle = track.title.escapeHTML();
				var artistName = track.artist.display_name.escapeHTML();
				var art_tag = '<img src="' + track.small_art_url + '" alt="' + trackTitle + ' by ' + artistName + '"/>';
				var snippet = this._trackInfoTemplate;
				snippet = snippet.replace(/TRACK_KEY/g, track.key);
				snippet = snippet.replace(/TRACK_TITLE/g, trackTitle);
				snippet = snippet.replace(/ARTIST_KEY/g, track.artist.key);
				snippet = snippet.replace(/ARTIST_NAME/g, artistName);
				snippet = snippet.replace(/SMALL_ART_TAG/g, art_tag);
				this._trackInfo.innerHTML = snippet;
				this._display.show();
			} else {
				this._display.hide();
			}
			this._updateScrubber();
		}
		if (disableMessage || initialMessage) {
			this._message.innerHTML = disableMessage ? disableMessage : initialMessage;
			this._display.hide();
			if (this._rater) {this._rater.setTrack(null);}
			this._message.show();
		} else {
			this._message.hide();
		}
	},

	_updateControls: function() {
		if (this._master) {
			if (this._master.playing()) {
				this._pauseButton.show();
				this._playButton.hide();
				this._playButton.disable();
			} else {
				this._playButton.show();
				this._playButton.enable();
				this._pauseButton.hide();
			}
			this._nextButton.setEnabled(this._master.isNextTrackEnabled());
			this._prevButton.setEnabled(this._master.isPreviousTrackEnabled());
			this._volumeSlider.enable();
			this._volumeSlider.setValue(this._master.volume());
			if (this._master.disabledMessage) {
				this._playButton.disable();
				this._playButton.show();
				this._pauseButton.hide();
				this._nextButton.disable();
				this._prevButton.disable();
				this._volumeSlider.disable();
			}
		} else {
			this._playButton.disable();
			this._playButton.show();
			this._pauseButton.hide();
			this._nextButton.disable();
			this._prevButton.disable();
			this._volumeSlider.disable();
		}
	},

	_findMaster: function() {
		if (Cookie.get('playerOpen') == 'true')
		{
			var mw = window.open('', this._windowID, this._windowParams);
			if (mw && mw.master) {
				log('remote: connecting to existing master');
				window.focus();
				this.connect(mw.master);
				return true;
			}
		}
		return false;
	},

	_showMaster: function() {
		if (!this._findMaster()) {
			log('remote: opening new master');
			window.open('/player', this._windowID, this._windowParams);
			window.focus();
		}
		if (this._basePlayerDiv.getHeight() < this._originalPlayerHeight) {
			this._basePlayerDiv.setStyle({height: this._originalPlayerHeight + 'px'});
			if (window.ourResizer) window.ourResizer.measureLayout();	
		}
	}
});

Player.play = function(toPlay, fromUrl) {
	if (window.remote) {
	  toPlay.srcUrl = fromUrl;
	  window.remote.play(toPlay);
	}
};
Player.playlistDidChange = function(playlistKey) {
	if (window.remote) {
		window.remote.playlistDidChange(playlistKey);
	}
};
Player.observe = function(eventName, handler) {
	if (window.remote) {
		window.remote.observe(eventName, handler);
	}
};
Player.stopObserving = function(eventName, handler) {
	if (window.remote) {
		window.remote.stopObserving(eventName, handler);
	}
};
Player.currentTrack = function() {
	if (window.remote) {
		return window.remote.currentTrack();
	}
};
Player.disable = function(message) {
	if (window.remote) {
		window.remote.disable(message);
	}
};
Player.enable = function() {
	if (window.remote) {
		window.remote.enable();
	}
};
Player.load = function() {
	var r, m;
	r = $('player-remote');
	m = $('player-master');
	if (r) {
		r = new Player.Remote(r);
		if (window.disablePlayerMessage) {
			r.disable(window.disablePlayerMessage)
		} else {
			r.enable(window.initialMessage);
		}
	}
	if (m) {
		new Player.Master(m, r);
		m.up().addClassName('master');
	}
};
document.observe('dom:loaded', Player.load);
