define(["inputManager", "events", "globalize", "playbackManager", "connectionManager", "playMethodHelper", "layoutManager", "paper-icon-button-light", "css!./playerstats", "scrollStyles"], function(inputManager, events, globalize, playbackManager, connectionManager, playMethodHelper, layoutManager) {
	"use strict";

	function init(instance) {
		var button, parent = document.createElement("div");
		parent.classList.add("playerStats"), parent.classList.add("hide"), button = '<button type="button" is="paper-icon-button-light" class="playerStats-closeButton"><i class="md-icon">close</i></button>';
		parent.innerHTML = '<div class="playerStats-content">' + button + '<div class="playerStats-stats scrollY hiddenScrollY-hover scrollY-mini"></div></div>', (button = parent.querySelector(".playerStats-closeButton")) && button.addEventListener("click", function() {
			this.enabled(!1), events.trigger(this, "close")
		}.bind(instance)), document.body.appendChild(parent), instance.element = parent
	}
	function translateReason(reason) {
		return globalize.translate("" + reason)
	}
	function getDisplayBitrate(bitrate) {
		return 1e6 < bitrate ? (bitrate / 1e6).toFixed(1) + " Mbps" : Math.floor(bitrate / 1e3) + " Kbps"
	}
	function getStats(instance, player) {
		var statsPromise = player.getStats ? player.getStats() : Promise.resolve({}),
			sessionPromise = function(instance, player) {
				if (Date.now() - (instance.lastSessionTime || 0) < 1e4) return Promise.resolve(instance.lastSession);
				var apiClient = connectionManager.getApiClient(playbackManager.currentItem(player).ServerId);
				return apiClient.getSessions({
					deviceId: apiClient.deviceId()
				}).then(function(sessions) {
					return instance.lastSession = sessions[0] || {}, instance.lastSessionTime = Date.now(), Promise.resolve(instance.lastSession)
				}, function() {
					return Promise.resolve({})
				})
			}(instance, player);
		return Promise.all([statsPromise, sessionPromise]).then(function(responses) {
			var playerStats = responses[0].categories || [],
				session = responses[1],
				displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session),
				baseCategory = {
					stats: [],
					name: "&#x64AD;&#x653E;&#x4FE1;&#x606F;"
				};
			baseCategory.stats.unshift({
				label: "&#x64AD;&#x653E;&#x5F62;&#x5F0F;:",
				value: displayPlayMethod
			}), baseCategory.stats.unshift({
				label: "&#x64AD;&#x653E;&#x5668;:",
				value: player.name
			});
			var categories = [];
			categories.push(baseCategory);
			for (var i = 0, length = playerStats.length; i < length; i++) {
				var category = playerStats[i];
				"audio" === category.type ? category.name = "&#x97F3;&#x9891;&#x4FE1;&#x606F;" : "video" === category.type && (category.name = "&#x89C6;&#x9891;&#x4FE1;&#x606F;"), categories.push(category)
			}
			return session.TranscodingInfo && categories.push({
				stats: function(session, displayPlayMethod) {
					var videoCodec, audioCodec, totalBitrate, sessionStats = [];
					return session.TranscodingInfo && (videoCodec = session.TranscodingInfo.VideoCodec, audioCodec = session.TranscodingInfo.AudioCodec, totalBitrate = session.TranscodingInfo.Bitrate, session.TranscodingInfo.AudioChannels), videoCodec && sessionStats.push({
						label: "&#x89C6;&#x9891;&#x7F16;&#x7801;:",
						value: session.TranscodingInfo.IsVideoDirect ? videoCodec.toUpperCase() + " (Direct)" : videoCodec.toUpperCase()
					}), audioCodec && sessionStats.push({
						label: "&#x97F3;&#x9891;&#x7F16;&#x7801;:",
						value: session.TranscodingInfo.IsAudioDirect ? audioCodec.toUpperCase() + " (Direct)" : audioCodec.toUpperCase()
					}), "Transcode" === displayPlayMethod && (totalBitrate && sessionStats.push({
						label: "&#x8F6C;&#x6362;&#x7801;&#x7387;(Bit):",
						value: getDisplayBitrate(totalBitrate)
					}), session.TranscodingInfo.CompletionPercentage && sessionStats.push({
						label: "&#x8F6C;&#x7801;&#x5B8C;&#x6210;&#x5EA6;:",
						value: session.TranscodingInfo.CompletionPercentage.toFixed(1) + "%"
					}), session.TranscodingInfo.Framerate && sessionStats.push({
						label: "&#x8F6C;&#x7801;&#x5E27;&#x901F;&#x7387;:",
						value: session.TranscodingInfo.Framerate + " fps"
					}), session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length && sessionStats.push({
						label: "&#x8F6C;&#x7801;&#x7684;&#x539F;&#x56E0;:",
						value: session.TranscodingInfo.TranscodeReasons.map(translateReason).join("<br/>")
					})), sessionStats
				}(session, displayPlayMethod),
				name: "&#x8F6C;&#x7801;" === displayPlayMethod ? "&#x8F6C;&#x7801;&#x4FE1;&#x606F;" : "&#x5F53;&#x524D;&#x64AD;&#x653E;&#x6E90;&#x4FE1;&#x606F;"
			}), categories.push({
				stats: function(player) {
					var sessionStats = [],
						mediaSource = playbackManager.currentMediaSource(player) || {},
						totalBitrate = mediaSource.Bitrate;
					mediaSource.Container && sessionStats.push({
						label: "&#x5A92;&#x4F53;&#x6E90;&#x683C;&#x5F0F;:",
						value: mediaSource.Container
					}), totalBitrate && sessionStats.push({
						label: "&#x6BD4;&#x7279;&#x7387;(Bit):",
						value: getDisplayBitrate(totalBitrate)
					});
					var videoStream = (mediaSource.MediaStreams || []).filter(function(s) {
						return "Video" === s.Type
					})[0] || {},
						videoCodec = videoStream.Codec,
						audioStreamIndex = playbackManager.getAudioStreamIndex(player),
						audioStream = playbackManager.audioTracks(player).filter(function(s) {
							return "Audio" === s.Type && s.Index === audioStreamIndex
						})[0] || {},
						audioCodec = audioStream.Codec,
						audioChannels = audioStream.Channels,
						videoInfos = [];
					videoCodec && videoInfos.push(videoCodec.toUpperCase()), videoStream.Profile && videoInfos.push(videoStream.Profile), videoInfos.length && sessionStats.push({
						label: "&#x89C6;&#x9891;&#x7F16;&#x7801;:",
						value: videoInfos.join(" ")
					}), videoStream.BitRate && sessionStats.push({
						label: "&#x89C6;&#x9891;&#x7801;&#x7387;:",
						value: getDisplayBitrate(videoStream.BitRate)
					}), (videoStream.AverageFrameRate || videoStream.RealFrameRate) && sessionStats.push({
						label: "&#x89C6;&#x9891;&#x5E27;&#x901F;&#x7387;:",
						value: (videoStream.AverageFrameRate || videoStream.RealFrameRate) + " fps"
					});
					var audioInfos = [];
					return audioCodec && audioInfos.push(audioCodec.toUpperCase()), audioStream.Profile && audioInfos.push(audioStream.Profile), audioInfos.length && sessionStats.push({
						label: "&#x97F3;&#x9891;&#x7F16;&#x7801;:",
						value: audioInfos.join(" ")
					}), audioStream.BitRate && sessionStats.push({
						label: "&#x97F3;&#x9891;&#x7801;&#x7387;:",
						value: getDisplayBitrate(audioStream.BitRate)
					}), audioChannels && sessionStats.push({
						label: "&#x97F3;&#x9891;&#x58F0;&#x9053;:",
						value: audioChannels
					}), audioStream.SampleRate && sessionStats.push({
						label: "&#x97F3;&#x9891;&#x91C7;&#x6837;&#x7387;:",
						value: audioStream.SampleRate + " Hz"
					}), audioStream.BitDepth && sessionStats.push({
						label: "&#x97F3;&#x9891;&#x4F4D;&#x6DF1;&#x5EA6;",
						value: audioStream.BitDepth
					}), sessionStats
				}(player),
				name: "&#x5A92;&#x4F53;&#x6E90;&#x6587;&#x4EF6;&#x4FE1;&#x606F;"
			}), Promise.resolve(categories)
		})
	}
	function renderPlayerStats(instance, player) {
		var now = Date.now();
		now - (instance.lastRender || 0) < 700 || (instance.lastRender = now, getStats(instance, player).then(function(stats) {
			var elem = instance.element;
			elem &&
			function(elem, categories) {
				elem.querySelector(".playerStats-stats").innerHTML = categories.map(function(category) {
					var categoryHtml = "",
						stats = category.stats;
					stats.length && category.name && (categoryHtml += '<div class="playerStats-stat playerStats-stat-header">', categoryHtml += '<div class="playerStats-stat-label">', categoryHtml += category.name, categoryHtml += "</div>", categoryHtml += '<div class="playerStats-stat-value">', categoryHtml += category.subText || "", categoryHtml += "</div>", categoryHtml += "</div>");
					for (var i = 0, length = stats.length; i < length; i++) {
						categoryHtml += '<div class="playerStats-stat">';
						var stat = stats[i];
						categoryHtml += '<div class="playerStats-stat-label">', categoryHtml += stat.label, categoryHtml += "</div>", categoryHtml += '<div class="playerStats-stat-value">', categoryHtml += stat.value, categoryHtml += "</div>", categoryHtml += "</div>"
					}
					return categoryHtml
				}).join("")
			}(elem, stats)
		}))
	}
	function unbindEvents(instance, player) {
		var onTimeUpdate = instance.onTimeUpdate;
		onTimeUpdate && events.off(player, "timeupdate", onTimeUpdate);
		var onInputCommand = instance.onInputCommand;
		onInputCommand && inputManager.off(instance.element, onInputCommand)
	}
	function PlayerStats(options) {
		this.options = options, this.onTimeUpdate = function() {
			var options = this.options;
			options && renderPlayerStats(this, options.player)
		}.bind(this), this.onInputCommand = function(e) {
			switch (e.detail.command) {
			case "back":
				break;
			case "left":
			case "right":
			case "pageup":
			case "pagedown":
			case "up":
			case "down":
				e.stopPropagation();
				break;
			case "select":
			case "menu":
			case "info":
			case "movies":
			case "music":
			case "tv":
			case "settings":
			case "nowplaying":
			case "search":
			case "favorites":
			case "livetv":
			case "recordedtv":
			case "guide":
				e.preventDefault()
			}
		}.bind(this), init(this), this.enabled(!0)
	}
	return PlayerStats.prototype.enabled = function(enabled) {
		if (null == enabled) return this._enabled;
		var options = this.options;
		options && ((this._enabled = enabled) ? (this.element.classList.remove("hide"), function(instance, player) {
			var onTimeUpdate = instance.onTimeUpdate;
			onTimeUpdate && events.on(player, "timeupdate", onTimeUpdate);
			var onInputCommand = instance.onInputCommand;
			onInputCommand && inputManager.on(instance.element, onInputCommand)
		}(this, options.player)) : (this.element.classList.add("hide"), unbindEvents(this, options.player)))
	}, PlayerStats.prototype.toggle = function() {
		this.enabled(!this.enabled())
	}, PlayerStats.prototype.destroy = function() {
		var options = this.options;
		options && (this.options = null, unbindEvents(this, options.player));
		var elem = this.element;
		elem && (elem.parentNode.removeChild(elem), this.element = null), this.onTimeUpdate = null, this.onInputCommand = null
	}, PlayerStats
});