Math.log10 = function (v) { return Math.log(v) / Math.LN10; };

if (Juviewer.lang == 'en') {
	Juviewer.tr = {
		gl_rank: '(Rank)', gl_points: 'Points', gl_basic: 'Average points (BASIC)',
		gl_advanced: 'Average points (ADVANCED)', gl_extreme: 'Average points (EXTREME)',
		go_all: 'All', go_6m: 'Recent 6 months', go_2m: '2 months',
		go_3w: '3 weeks', go_1w: 'Last week',
		ml_hidemusicbar: 'Hide Music Bar', ml_showmusicbar: 'Show Music Bar'
	};
} else if (Juviewer.lang == 'ko') {
	Juviewer.tr = {
		gl_rank: '(순위)', gl_points: '클래스 포인트', gl_basic: 'BASIC 평균 점수',
		gl_advanced: 'ADVANCED 평균 점수', gl_extreme: 'EXTREME 평균 점수',
		go_all: '전체', go_6m: '최근 6개월', go_2m: '최근 2개월',
		go_3w: '최근 3주', go_1w: '지난주',
		ml_hidemusicbar: '뮤직바 숨기기', ml_showmusicbar: '뮤직바 보이기'
	};
}

Juviewer.plots = function(points, pointsrank, basic, basicrank, advanced, advancedrank, extreme, extremerank) {
	function currenttime() {
		var now = new Date();
		return now.getTime() - now.getTimezoneOffset() * 60000;
	}

	function logyaxis(data) {
		var result = [];
		for (var i = 0; i < data.length; ++i) {
			result.push([data[i][0], -Math.log10(data[i][1])]);
		}
		return result;
	}

	function incronly(data) {
		var result = [data[0]], last = data[0][1];
		for (var i = 1; i < data.length; ++i) {
			if (data[i][1] > last) result.push(data[i]);
			last = data[i][1];
		}
		return result;
	}

	function cliprange(data, min) {
		var result = [];
		for (var i = 1; i < data.length; ++i) {
			if (data[i][0] >= min) result.push(data[i-1]);
		}
		if (data[data.length-1][0] >= min) result.push(data[data.length-1]);
		return result;
	}

	function plot_to(target, series) {
		var ticksformatter = function (v) {
			return v.toFixed(); // no trailing decimal point
		};

		var ticksgenerator = function (axis) {
			//var units = [1, 1.5, 2, 3, 4, 5, 6, 8];
			var units = [1, 1.5, 2.5, 4, 6]; // R5" series (ISO 3)

			var result = [];
			var min = Math.pow(10, -axis.max), max = Math.pow(10, -axis.min);
			var base = Math.pow(10, Math.floor(-axis.max));
			for (; base <= max; base *= 10) {
				for (var j = 0; j < units.length; ++j) {
					var value = units[j] * base;
					if (value < min || value > max) continue;
					result.unshift([-Math.log10(value), value]);
				}
			}

			// if there are few (<6) log-scale ticks, use uniform-scale ticks instead
			// (why 6? this is suggested by original flot source, derived from
			//  the equation: #ticks = 0.3 * sqrt(height).)
			var minnticks = 6;
			if (result.length < minnticks) {
				var delta = (max - min) / minnticks;
				var mag = Math.pow(10, Math.floor(Math.log10(delta)));
				var norm = delta / mag;
				norm = (norm < 1.5 ? 1 : norm < 3 ? 2 : norm < 7.5 ? 5 : 10);
				delta = mag * norm;
				if (delta < 1) delta = 1;

				result = [];
				var normmin = Math.floor(min / delta) * delta;
				if (normmin < min) normmin += delta;
				for (var v = normmin; v <= max; v += delta) {
					result.unshift([-Math.log10(v), v]);
				}
			}

			return result;
		};

		var options = {
			grid: {backgroundColor: '#fff'},
			xaxis: {mode: 'time', min: null, max: currenttime(),
				       minTickSize: [1, 'day'], timeformat: '%m/%d'},
			yaxis: {minTickSize: 10, tickFormatter: ticksformatter},
			y2axis: {minTickSize: 1, ticks: ticksgenerator},
			legend: {position: 'se', noColumns: 3}};

		var graphoption = $('<p class="graphoption">' + 
			'<a href="#all">' + Juviewer.tr.go_all + '</a> · ' +
			'<a href="#6m">' + Juviewer.tr.go_6m + '</a> · ' +
			'<a href="#2m">' + Juviewer.tr.go_2m + '</a> · ' +
			'<a href="#3w">' + Juviewer.tr.go_3w + '</a> · ' +
			'<a href="#1w">' + Juviewer.tr.go_1w + '</a></p>');
		var realgraph = $('<div class="realgraph"></div>');
		target.empty();
		target.append(graphoption);
		target.append(realgraph);

		var makecallback = function (limit) {
			return function () {
				var newseries = series, newoptions = options;
				if (limit != null) {
					var min = currenttime() - limit;
					newseries = [];
					for (var i = 0; i < series.length; ++i) {
						var s = $.extend(true, {}, series[i]); // deep copy
						s.data = cliprange(s.data, min);
						newseries.push(s);
					}
					newoptions = $.extend(true, {}, options); // ditto
					newoptions.xaxis.min = min;
				}

				var plot = $.plot(realgraph, newseries, newoptions);
				graphoption.css('margin-left', plot.getPlotOffset().left);
				realgraph.data('plot', plot);
				return false;
			};
		};

		// MSIE 6 "mutates" href field and requires $= instead of =.
		target.find('.graphoption [href$=#all]').click(makecallback(null));
		target.find('.graphoption [href$=#6m]').click(makecallback(15768000000));
		target.find('.graphoption [href$=#2m]').click(makecallback(5256000000));
		target.find('.graphoption [href$=#3w]').click(makecallback(1814400000)).click();
		target.find('.graphoption [href$=#1w]').click(makecallback(604800000));
	}

	var pointsrank = logyaxis(pointsrank);
	var basicrank = logyaxis(basicrank);
	var advancedrank = logyaxis(advancedrank);
	var extremerank = logyaxis(extremerank);
	var plotargs = [
		[$('#points-graph .graph'), [
			{data: points, label: Juviewer.tr.gl_points,
			 yaxis: 1, lines: {show: true}, points: {show: true}, color: '#444'},
			{data: pointsrank, label: Juviewer.tr.gl_rank,
			 yaxis: 2, lines: {lineWidth: 1}, color: '#888'},
			{data: incronly(pointsrank), yaxis: 2,
			 points: {show: true, lineWidth: 1.5}, color: '#888'}]],
		[$('#bscscore-graph .graph'), [
			{data: basic, label: Juviewer.tr.gl_basic,
			 yaxis: 1, lines: {show: true}, points: {show: true}, color: '#4c4'},
			{data: basicrank, label: Juviewer.tr.gl_rank,
			 yaxis: 2, lines: {lineWidth: 1}, color: '#8f8', hoverable: false},
			{data: incronly(basicrank), yaxis: 2,
			 points: {show: true, lineWidth: 1.5}, color: '#8f8'}]],
		[$('#advscore-graph .graph'), [
			{data: advanced, label: Juviewer.tr.gl_advanced,
			 yaxis: 1, lines: {show: true}, points: {show: true}, color: '#cc4'},
			{data: advancedrank, label: Juviewer.tr.gl_rank,
			 yaxis: 2, lines: {lineWidth: 1}, color: '#ff8', hoverable: false},
			{data: incronly(advancedrank), yaxis: 2,
			 points: {show: true, lineWidth: 1.5}, color: '#ff8'}]],
		[$('#extscore-graph .graph'), [
			{data: extreme, label: Juviewer.tr.gl_extreme,
			 yaxis: 1, lines: {show: true}, points: {show: true}, color: '#c44'},
			{data: extremerank, label: Juviewer.tr.gl_rank,
			 yaxis: 2, lines: {lineWidth: 1}, color: '#f88', hoverable: false},
			{data: incronly(extremerank), yaxis: 2,
			 points: {show: true, lineWidth: 1.5}, color: '#f88'}]]];

	// MSIE has multiple bugs in flot + jqueryui integration.
	var redrawrequired = jQuery.browser.msie;
	var tabs = $('#graph-tabs').tabs({
		show: function (event, ui) {
			if (plotargs[ui.index]) {
				plot_to.apply(null, plotargs[ui.index]);
				if (!redrawrequired) plotargs[ui.index] = null;
			}
		}
	});
	if (redrawrequired) {
		setTimeout(function () {
			plot_to.apply(null, plotargs[tabs.tabs('option', 'selected')]);
		}, 10);
	}
}

$(function () {
	// expand music list link to the rows
	$('.musiclist tr:not(.more)').each(function () {
		var href = $(this).find('a').attr('href');
		var rows = $(this).next('tr').filter('.more').add(this);
		rows.hover(function () { rows.addClass('hovering'); },
			function () { rows.removeClass('hovering'); });
		rows.click(function () { window.location.href = href; return false; });
	});

	// add dynamic options to u_musiclist
	$('#view-options').append('<a id="toggle-musicbar-button" href="#">' +
		Juviewer.tr.ml_hidemusicbar + '</a>');
	var musicbarshown = true;
	$('#toggle-musicbar-button').click(function () {
		musicbarshown = !musicbarshown;
		$('.musiclist tr.more').toggle(musicbarshown);
		$(this).text(musicbarshown ? Juviewer.tr.ml_hidemusicbar : Juviewer.tr.ml_showmusicbar);
		return false;
	});
});

