(function($) {	
	$.ytplayer = {
		version: '0.0.1',

		defaultConf: {
			source: null,
			native: false,
			autoplay: false,
			buffering: false,
			width: null,
			height: null,
			template: ".YTPlayerTemplate",
			onReady: null,
			onPlay: null,
			onPause: null,
			onStop: null
		},
		
		defaultTemplate:  '\
			<div class="ytp-wrapper ytp-wrapper-widget">\
				<div class="ytp-wrapper ytp-wrapper-object">\
					<div id="<%=playerId%>"></div>\
				</div>\
				<div class="ytp-wrapper ytp-wrapper-controls">\
					<div class="ytp-controls">\
						<div class="ytp-control ytp-control-button ytp-control-button-play png"></div>\
						<div class="ytp-control ytp-control-button ytp-control-button-previous png"></div>\
						<div class="ytp-control ytp-control-button ytp-control-button-next png"></div>\
						<div class="ytp-control ytp-control-slider ytp-control-slider-time"></div>\
						<div class="ytp-control ytp-control-button ytp-control-button-mute png">\
							<div class="ytp-wrapper ytp-wrapper-control-slider-volume">\
								<div class="ytp-control ytp-control-slider ytp-control-slider-volume"></div>\
							</div>\
						</div>\
						<div class="ytp-control ytp-control-logo png">\
					</div>\
				</div>\
			</div>\
		'
	};
	
	window.onYouTubePlayerReady = function(playerId) {
		$("."+playerId).data("ytplayer").onYouTubePlayerReady(playerId);
	}
	
	function YTPlayer(conf, root) { 
			var self = this, $self = $(this), current;
			
			var template = root.find(conf.template),
				template = template.length ? template : $("<script type='text/html'>"+$.ytplayer.defaultTemplate+"</script>"),
				identifier = "ytplayer_" + (new Date() - 0),
				identifierBuffer = identifier + "_buffer";
			
			// bind all callbacks from configuration
			$.each(conf, function(name, fn) {
				if ($.isFunction(fn)) { $self.bind(name, fn); }
			});
			
			// public methods
			$.extend(this, {
				isYtplayer: true,
				onYouTubePlayerReady: function(playerId) {
					if (playerId == identifier) {
						self._player = document.getElementById(playerId);
						self._player.addEventListener("onStateChange", self.getPlayerStateChangeName(playerId));
						$self.trigger("onReady", [self]);
					} else if (playerId == identifierBuffer) {
						self._playerBuffer = document.getElementById(playerId);
						self._playerBuffer.addEventListener("onStateChange", self.getPlayerStateChangeName(playerId));
						$(self._playerBuffer).addClass("ytp-object-hidden");
						return;
					} else {
						return;
					}
					
					self.videoId(conf.source);
					
					if (self.videoId()) {
						if (conf.autoplay) {
							self.getPlayer().loadVideoById(self.videoId(), self._seekto);
						} else {
							self.getPlayer().cueVideoById(self.videoId(), self._seekto);
						}
					}
					
					setInterval(function() {
						var getBytesTotal = self.getPlayer().getVideoBytesTotal(),
							getStartBytes = self.getPlayer().getVideoStartBytes(),
							getBytesLoaded = self.getPlayer().getVideoBytesLoaded();
						
						var startPercent = (getStartBytes <= 0) ? 0 : getStartBytes/getBytesTotal*100,
							endPercent = (getBytesLoaded <= 0) ? 0 : getBytesLoaded/getBytesTotal*100;
						
						var currentTime = self.getCurrentTime(),
							currentTimePercent = (currentTime <= 0) ? 0 : currentTime/self.getDuration()*100;

						$self.trigger("onUpdateCurrentTime", [currentTime, currentTimePercent]);
						$self.trigger("onUpdateLoadData", [startPercent, endPercent]);
						if (100 == endPercent && self.videoId() !== self._cancelLoadDataVideoId) {
							self._cancelLoadDataVideoId = self.videoId();
							$self.trigger("onCancelLoadData");
						}
					}, 250);
				},
				
				updateYTPlayerInfo: function() {
					
				},
				
				getPlayerStateChangeName: function(id) {
					var playerStateChangeName = "onYTPlayerStateChange_" + id;
					window[playerStateChangeName] = function(newState) {
						if (id !== self.getPlayer().id) {
							return;
						}
						
						switch(newState) {
							case 0:
							$self.trigger("onStop");
							break;
							case 1:
							$self.trigger("onPlay");
							break;
							case 2:
							$self.trigger("onPause");
							break;
							case 3:
							$self.trigger("onBuffering");
							break;
							case 5:
							$self.trigger("onCue");
							break;
							default: return;
						}

						if (0 == newState || 2 == newState || 5 == newState) {
							$self.trigger("onSetPlayIcon");
						} else {
							$self.trigger("onSetPauseIcon");
						}
					}

					return playerStateChangeName;
				},
				
				bufferingVideo: function(videoId) {
					if (!conf.buffering) {
						return;
					}
					
					self._bufferVideoId = videoId;
					
					self.getBufferPlayer().stopVideo();
					self.getBufferPlayer().clearVideo();
					self.getBufferPlayer().cueVideoById(self._bufferVideoId, 0);
				},
				
				playVideo: function(videoId) {
					if (conf.buffering && self._bufferVideoId == videoId) {
						self._activeBuffer = !self._activeBuffer;
						$(self._player).toggleClass("ytp-object-hidden");
						$(self._playerBuffer).toggleClass("ytp-object-hidden");
						
						if (self.getPlayer().getVideoBytesLoaded() > 0) {
							self.videoId(videoId)
							self.getPlayer().playVideo();
							return
						}
					}
					
					self.getPlayer().stopVideo();
					self.getPlayer().clearVideo();
					self.getPlayer().loadVideoById(self.videoId(videoId), 0);
				},
				
				cueVideo: function(videoId) {
					self.getPlayer().cueVideoById(self.videoId(videoId), 0);
				},
				
				isPause: function() {
					var realState = self.getPlayer().getPlayerState();
					return (0 == realState || 2 == realState || 5 == realState);
				},
				
				isPlay: function() {
					return !self.isPause();
				},
				
				getPlayer: function() {
					return (!self._activeBuffer) ? self._player : self._playerBuffer;
				},
				
				getBufferPlayer: function() {
					return (self._activeBuffer) ? self._player : self._playerBuffer;
				},
				
				videoId: function(id) {
					if (id) {
						self._videoId = id;
						self._cancelLoadDataVideoId = null;
						$self.trigger("onChangeVideo", [self._videoId]);
					}
					return self._videoId;
				},
				
				play: function() {
					self.getPlayer().playVideo();
				},
				
				pause: function() {
					self.getPlayer().pauseVideo();
				},
				
				stop: function() {
					self.getPlayer().stopVideo();
				},
				
				seekTo: function(seconds) {
					self._seekto = seconds;
					self.getPlayer().seekTo(seconds, true);
				},
				
				seekToPercent: function(percent) {
					var seconds = self.getDuration()/100*percent;
					self.seekTo(seconds);
				},
				
				getDuration: function() {
					return self.getPlayer().getDuration();
				},
				
				getCurrentTime: function() {
					return self.getPlayer().getCurrentTime();
				},
				
				volume: function(volume) {
					if ("undefined" !== typeof(volume)) {
						self.getPlayer().setVolume(volume);
					}
					return self.getPlayer().getVolume();
				},
				
				mute: function(mute) {
					if ("undefined" !== typeof(mute)) {
						if (mute) {
							self.getPlayer().mute();
						} else {
							self.getPlayer().unMute();
						}
					}
					
					return self.getPlayer().isMuted();
				}
			});
			
			
			
			self._player = null;
			self._playerBuffer = null;
			self._videoId = null;
			self._bufferVideoId = null;
			self._seekto = 0;
			self._activeBuffer = false;
			
			if (conf.buffering) {
				$self.bind("onCancelLoadData", function() {
					self.getBufferPlayer().playVideo();
					self.getBufferPlayer().pauseVideo();
					self.getBufferPlayer().clearVideo();
				});
			}
			
			root.html(template.tmpl({
				playerId: identifier
			}));
			
			if (!conf.native) {
				root.find(".ytp-control-button").mouseenter(function(){
					$(this).addClass("ytp-control-button-hover");
				}).mouseleave(function(){
					$(this).removeClass("ytp-control-button-hover");
				})

				var playButton			 = root.find(".ytp-control-button-play"),
					previousButton		 = root.find(".ytp-control-button-previous"),
					nextButton			 = root.find(".ytp-control-button-next"),
					muteButton			 = root.find(".ytp-control-button-mute"),
					timeSlider			 = root.find(".ytp-control-slider-time"),
					volumeSlider		 = root.find(".ytp-control-slider-volume"),
					wrapperVolumeSlider	 = root.find(".ytp-wrapper-control-slider-volume");

				timeSlider.width((muteButton.offset().left - timeSlider.offset().left - 10)+"px");

				playButton.click(function(){
					if (self.isPause()) {
						self.play();
					} else {
						self.pause();
					}

				});
				
				previousButton.click(function(){
					$self.trigger("onPrevious");
				});
				
				nextButton.click(function(){
					$self.trigger("onNext");
				});

				timeSlider.slider({
					range: "min",
					step: 0.1,
					value: 0,
					min: 0,
					max: 100,
					start: function(event, ui) {
						timeSlider.data("isSlide", true);
					},
					stop: function(event, ui) {
						timeSlider.data("isSlide", false);
					},
					slide: function(event, ui) {
						self.seekToPercent(ui.value);
					}
				});

				wrapperVolumeSlider.hide();

				var hideVolumeWrapper = function() {
					var hideTimeout = wrapperVolumeSlider.data("hideTimeout");
					clearTimeout(hideTimeout);

					hideTimeout = setTimeout(function(){
						if (!volumeSlider.data("isSlide") && !volumeSlider.data("mouseenter")) {
							wrapperVolumeSlider.hide();
						}
					}, 1000);
					wrapperVolumeSlider.data("hideTimeout", hideTimeout);
				}

				muteButton.mouseenter(function(){
					volumeSlider.data("mouseenter", true);
					wrapperVolumeSlider.show();
				});

				muteButton.mouseleave(function(){
					volumeSlider.data("mouseenter", false);
					hideVolumeWrapper();
				});

				volumeSlider.slider({
					orientation: "vertical",
					range: "min",
					min: 0,
					max: 100,
					value: 50,
					start: function(event, ui) {
						volumeSlider.data("isSlide", true);
					},
					stop: function(event, ui) {
						volumeSlider.data("isSlide", false);
						hideVolumeWrapper();
					},
					slide: function(event, ui) {
						if (0 == ui.value) {
							muteButton.addClass("ytp-control-button-mute-mute");
							self.mute(true);
						} else {
							muteButton.removeClass("ytp-control-button-mute-mute");
							self.mute(false);
						}

						self.volume(ui.value);
					}
				});

				muteButton.click(function(){
					if(self.mute()) {
						muteButton.removeClass("ytp-control-button-mute-mute");
						self.mute(false);
						volumeSlider.slider("value", self.volume());
					} else {
						muteButton.addClass("ytp-control-button-mute-mute");
						self.mute(true);
						volumeSlider.slider("value", 0);
					}
				});



				timeSlider.prepend('<div class="ytp-control-indicator-load"></div>');

				var loadIndicator = root.find(".ytp-control-indicator-load");

				$self.bind("onUpdateCurrentTime", function(event, seconds, percent) {
					if (!timeSlider.data("isSlide")) {
						timeSlider.slider("value", percent);
					}
					//console.log(seconds, percent);
				});

				$self.bind("onUpdateLoadData", function(event, startPercent, endPercent) {
					loadIndicator.css("margin-left", startPercent + "%").css("width", endPercent + "%");
				});


				$self.bind("onSetPlayIcon", function() {
					playButton.removeClass("ytp-control-button-play-pause");
				});

				$self.bind("onSetPauseIcon", function() {
					playButton.addClass("ytp-control-button-play-pause");
				});
				
				$self.bind("onReady", function() {
					self.volume(volumeSlider.slider("value"));
				});
				
			} else {
				root.find(".ytp-wrapper-controls").remove();
			}
			
			function setSWFObject(id) {
				root.addClass(id);
				var swfobjectURL;
				if (!conf.native) {
					swfobjectURL = "http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid="+id;
				} else {
					swfobjectURL = "http://www.youtube.com/v/"+conf.source+"?enablejsapi=1&playerapiid="+id;
				}
				//swfobject.embedSWF(playerUrl + '&rel=1&border=0&fs=1&autoplay=' + (autoplay?1:0), 'player', '290', '250', '9.0.0', false, false, {allowfullscreen: 'true'});

				var objectElement = $("#" + id),
					width = (conf["width"]) ? conf["width"] : objectElement.width(),
					height = (conf["height"]) ? conf["height"] : width/4*3;

					objectElement.height(height);
				
				//console.log(root.find(".ytp-wrapper-object"))
				root.find(".ytp-wrapper-object").height(height).width(width);

				var params = { allowScriptAccess: "always", allowfullscreen: "true", bgcolor: "#000000", wmode: "transparent" };
				var atts = { id: id };
				swfobject.embedSWF(swfobjectURL, id, width, height, "8", null, null, params, atts);
				
				return objectElement;
			}
			
			var objectElement = setSWFObject(identifier);
			
			if (conf.buffering) {
				var bufferObjectElement = $('<div id="'+identifierBuffer+'" class="ytp-object-buffer"></div>');
				objectElement.after(bufferObjectElement);
				
				setSWFObject(identifierBuffer);
			}
	}
	
	// jQuery plugin implementation
	$.fn.ytplayer = function(conf) {
		var conf = $.extend($.ytplayer.defaultConf, conf);
		
		if (!conf.source) {
			conf.native = false;
		} else {
			var results = conf.source.match("[\\?&]v=([^&#]*)");
			conf.source = ( results === null ) ? conf.source : results[1];
		}
		
		return this.each(function(i) {				
			var root = $(this);
			
			if (root.data("ytplayer")) {
				return;
			}
			
			root.data("ytplayer", new YTPlayer(conf, root));
		});
	};		
		
}) (jQuery); 
