var analyticsModule = (function () {

	d3.selection.prototype.first = function () {
		return d3.select(this[0][0]);
	};
	d3.selection.prototype.last = function () {
		var last = this.size() - 1;
		return d3.select(this[0][last]);
	};

	var _dataCache = {
    'statistic': {},
		'levels': {}
	};

	var $_preloader,
		_isNewUser,
		_period;

	var LEVEL_NAME = {
		excellent: 'Отлично',
		good: 'Хорошо',
		satisfactorily: 'Средне',
		bad: 'Плохо',
		bad_time: 'Медленно',
		excellent_time: 'Очень быстро'
	};

	var _getDonutReviewValues = function (period) {
		var metrics = _dataCache['statistic'][period];
		var good = 0, bad = 0, empty = 0, repeatWOReview = 0, noReviews = 0;

		if (metrics.hasOwnProperty('review_good')) {
			good = metrics['review_good'].value ^ 0;
		}

		if (metrics.hasOwnProperty('review_repeat')) {
			repeatWOReview = metrics['review_repeat'].value ^ 0;
		}

		if (metrics.hasOwnProperty('review_bad')) {
			bad = metrics['review_bad'].value ^ 0;
		}

		if (metrics.hasOwnProperty('review_empty')) {
			empty = metrics['review_empty'].value ^ 0;
		}

		if (good + bad + empty + repeatWOReview == 0) {
			noReviews = -1;
		}

		var total = good + bad + empty + repeatWOReview;

		var goodColumns = [
			['Положительных', good * 100 / total],
			['Повторные заказы', repeatWOReview * 100 / total]
		];
		goodColumns.sort(_sortColumns);

		var badColumns = [
			['Отрицательных', bad * 100 / total],
			['Без отзыва', empty * 100 / total]
		];
		badColumns.sort(_sortColumns);

		noReviews = [['Нет заказов', noReviews]];
		$.merge(badColumns, noReviews);

		return $.merge(goodColumns, badColumns, ['Нет заказов', noReviews]);
	};

	var _sortColumns = function (a, b) {
		return a[1] < b[1] ? 1 : -1;
	};

	var _getDonutCancellationValues = function (period) {
		var metrics = _dataCache['statistic'][period];
		var done = 0, cancellation = 0, autoCancel = 0, expirationCancel = 0, noOrders = 0;

		if (metrics.hasOwnProperty('done_orders')) {
			done = metrics['done_orders'].value ^ 0;
		}

		if (metrics.hasOwnProperty('cancellation')) {
			cancellation = metrics['cancellation'].value ^ 0;
		}

		if (metrics.hasOwnProperty('auto_cancel')) {
			autoCancel = metrics['auto_cancel'].value ^ 0;
		}

		if (metrics.hasOwnProperty('expiration_cancel')) {
			expirationCancel = metrics['expiration_cancel'].value ^ 0;
		}

		if (done + cancellation + autoCancel + expirationCancel == 0) {
			noOrders = -1;
		}

		var total = done + cancellation + autoCancel + expirationCancel + noOrders;

		var goodColumns = [
			['Выполнено', done * 100 / total]
		];
		goodColumns.sort(_sortColumns);

		var badColumns = [
			['Отказы', cancellation * 100 / total],
			['Автоотмены', autoCancel * 100 / total],
			['Отмена в пользу покупателя', expirationCancel * 100 / total]
    ];
		badColumns.sort(_sortColumns);

		noOrders = [['Нет заказов', noOrders]];
		$.merge(badColumns, noOrders);

		return $.merge(goodColumns, badColumns, [['Нет заказов', noOrders]]);
	};

	var _generateDonutChart = function (period, type) {
		var columns, selector, colorPattern;
		switch (type) {
			case 'reviews':
				selector = '.js-analytics__donut--reviews';
				columns = _getDonutReviewValues(period);
				colorPattern = {
					'Положительных': '#66AE47',
					'Повторные заказы': '#66AE47',
					'Отрицательных': '#F5594D',
					'Без отзыва': '#E7E7E7',
					'Нет заказов': '#E7E7E7',
					'Positive': '#66AE47',
					'Repeated orders': '#66AE47',
					'Negative': '#F5594D',
					'No feedback': '#E7E7E7',
					'No orders!': '#E7E7E7',
				};
				break;
			case 'cancellation':
				selector = '.js-analytics__donut--cancellation';
				columns = _getDonutCancellationValues(period);
				colorPattern = {
					'Выполнено': '#66AE47',
					'Отказы': '#F5594D',
					'Автоотмены': '#F5594D',
					'Отмена в пользу покупателя': '#F5594D',
					'Нет заказов': '#E7E7E7',
					'Completed': '#66AE47',
					'Refusals': '#F5594D',
					'Auto Cancel': '#F5594D',
					'Overdue with cancellation': '#F5594D',
					'No orders!': '#E7E7E7',
				};
				break;
		}

		var chart = c3.generate({
			bindto: selector,
			size: {
				height: 160,
				width: 160
			},
			tooltip: {
				show: false
			},
			legend: {
				show: false
			},
			data: {
				order: null,
				columns: columns,
				colors: colorPattern,
				type: 'donut',
				onmouseover: function (data) {
					if (data.value == -1) {
						return;
					}

					var percent = Math.round(data.ratio * 1000) / 10;
					var label = d3.select(selector + ' text.c3-chart-arcs-title');
					label.html('');
					label.insert('tspan')
						.text(percent + '%').attr('dy', -5).attr('x', 0).attr('fill', '#333')
						.attr('class', 'donut-chart-title-percent');

					if (data.name == 'Повторные заказы') {
						label.insert('tspan')
							.text('Без отзыва,').attr('dy', 15).attr('x', 0).attr('fill', '#333')
							.attr('class', 'donut-chart-title-name');
						label.insert('tspan')
							.text('повторные').attr('dy', 10).attr('x', 0).attr('fill', '#333')
							.attr('class', 'donut-chart-title-name');
						label.insert('tspan')
							.text('заказы').attr('dy', 10).attr('x', 0).attr('fill', '#333')
							.attr('class', 'donut-chart-title-name');
					} else if (data.name == 'Отмена в пользу покупателя') {
						label.insert('tspan')
							.text('В пользу').attr('dy', 15).attr('x', 0).attr('fill', '#333')
							.attr('class', 'donut-chart-title-name');
						label.insert('tspan')
							.text('покупателя').attr('dy', 10).attr('x', 0).attr('fill', '#333')
							.attr('class', 'donut-chart-title-name');
					} else {
						label.insert('tspan')
							.text(data.name).attr('dy', 15).attr('x', 0).attr('fill', '#333')
							.attr('class', 'donut-chart-title-name');
					}
				}
			},
			donut: {
				title: '',
				label: {
					show: false
				}
			},
			onrendered: function () {
				var data = {};
				var name = type == 'reviews' ? 'Положительных' : 'Выполнено';
				this.pie(this.filterTargetsToShow(this.data.targets)).forEach(function (t) {
					if (t.data.id === name) {
						data = t;
					}
				});

				var percent = Math.round(data.value * 10) / 10;
				var label = d3.select(selector + ' text.c3-chart-arcs-title');

				label.html('');
				label.insert('tspan')
					.text(percent + '%').attr('dy', -5).attr('x', 0).attr('fill', '#333')
					.attr('class', 'donut-chart-title-percent');

				label.insert('tspan')
					.text(name).attr('dy', 15).attr('x', 0).attr('fill', '#333')
					.attr('class', 'donut-chart-title-name');
			}
		});
	};

	var _getMonthName = function (month) {
		var months = {
			1: 'января',
			2: 'февраля',
			3: 'марта',
			4: 'апреля',
			5: 'мая',
			6: 'июня',
			7: 'июля',
			8: 'августа',
			9: 'сентября',
			10: 'октября',
			11: 'ноября',
			12: 'декабря'
		};

		return months[month];
	};

	var _generateLineChart = function (chartData, selector, lineColor, minTime) {
		var $$chartObject = {};

		var line = ['data'];
		var keys = Object.keys(chartData);
		var timeValues = _getLineChartTimeValues(minTime, keys.length);
		for (var i = 0; i < keys.length; i++) {
			var item = chartData[keys[i]];
			line.push(item.sum);
		}

		keys.unshift('x');

		var chart = c3.generate({
			bindto: selector,
			data: {
				x: 'x',
				columns: [
					keys,
					line
				],
				onmouseover: function (d) {
					var circle = $$chartObject.getCircles(d.index);
					circle.style("fill", '#FFF')
						.style("stroke", $$chartObject.color)
						.style("stroke-width", 3);
				},
				onmouseout: function (d) {
					var circle = $$chartObject.getCircles(d.index);
					circle.style("fill", $$chartObject.color)
						.style("stroke-width", 0);
				}
			},
			size: {
				height: 200
			},
			color: {
				pattern: [lineColor]
			},
			tooltip: {
				contents: function (d) {
					var dateFrom = d[0].x,
						days = dateFrom.getDate() < 10 ? '0' + dateFrom.getDate() : dateFrom.getDate(),
						month = dateFrom.getMonth() < 9 ? '0' + (dateFrom.getMonth() + 1) : dateFrom.getMonth() + 1,
						strDate = dateFrom.getFullYear() + '-' + month + '-' + days,
						salesTitle = Utils.declOfNum(chartData[strDate].count, ['продажа', 'продажи', 'продаж']);

					var dateTo = new Date(d[0].x);
					//dateTo.setDate(dateTo.getDate() + 6);
					var daysTo = dateTo.getDate() < 10 ? '0' + dateTo.getDate() : dateTo.getDate();

					if (!chartData.hasOwnProperty(strDate)) {
						return;
					}
					var currencyString = Utils.numberFormat(chartData[strDate].sum, 0, '.', ' ');
					currencyString += ' <span class="rouble">Р</span>';

					return '' +
						'<div class="chart-tooltip">' +
						'   <span class="chart-tooltip__value">'
						+ Utils.numberFormat(chartData[strDate].count, 0, '.', ' ') + ' ' + salesTitle + ', ' +
						currencyString + '</span><br>' +
						'   <span class="chart-tooltip__date">' +
						daysTo + ' ' + _getMonthName(dateTo.getMonth() + 1) + ' ' + dateTo.getFullYear() +
						'   </span>' +
						'</div>';
				}
			},
			axis: {
				x: {
					type: 'timeseries',
					tick: {
						fit: false,
						outer: true,
						count: 3,
						format: function (x) {
							return x.getDate() + ' ' + _getMonthName(x.getMonth() + 1);
						},
						values: timeValues.values
					},
					padding: {
						left: timeValues.padding.left,
						right: timeValues.padding.right
					},
					height: 35,
					min: timeValues.min,
					max: timeValues.max
				},
				y: {
					min: 0
				}
			},
			point: {
				r: 1.5,
				focus: {
					expand: {
						enabled: true,
						r: 7
					}
				}
			},
			regions: [
				{axis: 'x', class: 'background-block'}
			],
			legend: {
				show: false
			},
			line: {
				connectNull: true
			},
			onrendered: function () {
				$$chartObject = this;

				var ticks = $$chartObject.axes.x.selectAll('.tick text tspan');
        //ticks.attr('dx', '-10');
        //ticks.last().attr('dx', '-35');
        $$chartObject.axes.x.selectAll('.tick:nth-child(2) text tspan').attr('dx', '-10');
        $$chartObject.axes.x.selectAll('.tick:nth-child(3) text tspan').attr('dx', '-30');
        $$chartObject.axes.x.selectAll('.tick:nth-child(4) text tspan').attr('dx', '-50');

				var lastDate = new Date(timeValues.max);
				lastDate.setDate(lastDate.getDate() - 1);
				ticks.last().text(lastDate.getDate() + ' ' + _getMonthName(lastDate.getMonth() + 1));
			}
		});
	};

	var _getLineChartTimeValues = function (minTime, valuesCount) {
		var result = {};
		var currentDate = new Date();

		currentDate.setDate(currentDate.getDate() + 1);
		result.max = currentDate.getTime();

		if (_period > 0) {
			currentDate.setMonth(currentDate.getMonth() - _period);
      result.min = currentDate.getTime();
		} else {
			result.min = minTime;
		}

    result.min = minTime; /* start date by server */

		result.values = [
			result.min,
			result.min + (result.max - result.min) / 2,
			result.max
		];

		result.padding = {
			left: (result.max - result.min) * 3 / 100,
			right: (result.max - result.min) * 3 / 100
		};

		return result;
	};

	var _setPeriod = function () {
		_showPreloader();
		_period = $(this).val().toString();
    //location.href = 'analytics?type=' + _period;

    if (_dataCache['statistic'].hasOwnProperty(_period)) {
			_setStatistic();
			return;
		}
		$('.js-preloader--analytics').show();
		$.get('/api?method=mk_getstatistic&period=' + _period, function (response) {
			if (response.success == true) {
				_dataCache['statistic'][_period] = response['statistic'];

				_setStatistic();
			} else {
        location.href = 'analytics?type=' + _period;
      }
		}, 'json');

	};

	var _setEvents = function () {
		$('.js-analytics-period').on('change', _setPeriod);

		$.tooltipster.on('ready', function(event) {
			var $tooltip = $(event.instance.elementOrigin());
			var $tooltipContent = $('.tooltipster-content');

			$tooltipContent.find('.js-analytics-tooltip__hint').each(function () {
				var metricName = $(this).data('metric');
				var metric = _getMetricValue(metricName);

				var text = _fillTooltipValueText(metricName, metric);
				$(this).html(text);

				if (typeof metric == 'undefined' || metric['value_def'] == 0) {
					$('.js-hide-if-null--' + metricName).hide();
				} else {
					$('.js-hide-if-null--' + metricName).show();
				}
			});

			var cancellation = 0, autoCancel = 0, expirationCancel = 0;

			if (typeof _getMetricValue('cancellation') == 'object' && _getMetricValue('cancellation').hasOwnProperty('value_def')) {
				cancellation = _getMetricValue('cancellation').value_def ^ 0
			}
			if (typeof _getMetricValue('auto_cancel') == 'object' && _getMetricValue('auto_cancel').hasOwnProperty('value_def')) {
				autoCancel = _getMetricValue('auto_cancel').value_def ^ 0;
			}
			if (typeof _getMetricValue('expiration_cancel') == 'object' && _getMetricValue('expiration_cancel').hasOwnProperty('value_def')) {
				expirationCancel = _getMetricValue('expiration_cancel').value_def ^ 0;
			}

			if (cancellation == 0 && autoCancel == 0 && expirationCancel == 0) {
				$('.js-hide-if-null--metric-cancel').hide();
			}

			$tooltip.tooltipster('reposition');
		});

	};

	var _setPlural = function (value, $block) {
		var pluralForms = $block.data('plural');
		if (pluralForms == null) {
			return;
		}

		$block.text(Utils.declOfNum(value, pluralForms));
	};

	var _clearLevels = function ($el) {
		$el.removeClass('analytics-value--excellent analytics-value--good analytics-value--bad analytics-value--satisfactorily')
			.removeClass('analytics-value-bg--excellent analytics-value-bg--good analytics-value-bg--bad analytics-value-bg--satisfactorily')
	};

	var _addLevel = function ($el, level, type) {
		switch (type) {
			case 'text':
				if (($el.hasClass('js-metric__level-name--work_speed') || $el.hasClass('js-metric__level-name--reaction_time'))
					&& (level == 'excellent' || level == 'bad')) {
					level += '_time';
				}
				$el.text(LEVEL_NAME[level]);
				break;
			case 'background':
				$el.addClass(_getLevelClass(type, level));
				break;
			case 'color':
			default:
				$el.addClass(_getLevelClass(type, level));
				break;
		}
	};

	var _getLevelClass = function (type, level) {
		switch (type) {
			case 'background':
				return 'analytics-value-bg--' + level;
			case 'color':
			default:
				return 'analytics-value--' + level;
		}
	};

	var _getMetricValue = function (metricName) {
    return _dataCache['statistic'][_period][metricName];
	};

	var _setStatistic = function () {
		var keys = Object.keys(_dataCache['statistic'][_period]),
			periodValues = _dataCache['statistic'][_period];

		if (_isNewUser.default) {
			$('.js-metric__level-name').hide();
		}

		if (_isNewUser['responsibility']) {
			$('.js-metric__level-name--done_orders_percent').hide().next().hide();
		}
		if (_isNewUser['reviews']) {
			$('.js-metric__level-name--review_rating').hide().next().hide();
		}

		for (var i = 0; i < keys.length; i++) {
			var metricName = keys[i],
				metric = periodValues[keys[i]];
			$('.js-metric__value--' + metricName).html(metric.value);
			_setPlural(metric.value, $('.js-metric__title--' + metricName));

			var $levelBlock = $('.js-metric__level--' + metricName);
			_clearLevels($levelBlock);
			if (!_isNewUser.default) {
				_addLevel($levelBlock, metric.level, 'color');
			}
			_addLevel($('.js-metric__level-name--' + metricName), metric.level, 'text');

			var $bgBlock = $('.js-metric__level-bg--' + metricName);
			_clearLevels($bgBlock);
			_addLevel($bgBlock, metric.level, 'background');

			$('.js-metric__percent--' + metricName).width(metric.percent + '%');
		}

		if (typeof _getMetricValue('work_speed') != 'object' || (_getMetricValue('work_speed').value_def ^ 0) == 0) {
			$('.js-hide-if-null--work_speed').hide();
		} else {
			$('.js-hide-if-null--work_speed').show();
		}

		if (typeof _getMetricValue('reaction_time') != 'object' || (_getMetricValue('reaction_time').value_def ^ 0) == 0) {
			$('.js-hide-if-null--reaction_time').hide();
		} else {
			$('.js-hide-if-null--reaction_time').show();
		}

		_generateDonutChart(_period, 'reviews');
		_generateDonutChart(_period, 'cancellation');

		$('.total-sum-block__value').html(_dataCache['total-sum']);

		_hidePreloader();
	};

	var _fillTooltipValueText = function (metricName, metric) {
		switch (metricName) {
			case 'done_orders_percent':
				if (_isNewUser['responsibility']) {
					return '';
				}
				break;
			case 'review_rating':
				if (_isNewUser['reviews']) {
					return '';
				}
				break;
			default:
				if (_isNewUser['default']) {
					return '';
				}
		}

		var textParams = _getTooltipValueText(metricName),
			lessMore, percent;

		if (typeof metric == 'undefined') {
			lessMore = textParams.bad;
			percent = 99;
			metric = {
				level: 'bad',
				value: 0,
				'value_def': 0
			};
		} else if (metric['user_percent'].good < 40) {
			lessMore = textParams.bad;
			percent = metric['user_percent'].bad;
		} else {
			lessMore = textParams.good;
			percent = metric['user_percent'].good;
			if (metricName == 'done_orders_percent' && percent == 100) {
				lessMore = textParams.good100;
			}
		}

		var replaceParams = {
			'bad-good': lessMore,
			'value': '<span class="bold ' + _getLevelClass('color', metric.level) + '">' + metric.value + '</span>',
			'user_percent': '<span class="bold ' + _getLevelClass('color', metric.level) + '">' + percent + '%' + '</span>',
			'period': '',
			'hidden': metric['value_def'] == 0 ? 'hidden' : ''
		};

		var text = textParams.text;
		if (textParams.hasOwnProperty('zero') && metric['value'] == 0) {
			text = textParams.zero;
		}

		return text.replace(/({{.*?}})/g, function (str, p) {
			var param = p.replace(/([{}]*)?/g, '');
			return replaceParams[param];
		});
	};

	var _getTooltipValueText = function (metricName) {
		var texts = {
			review_rating: {
				text: 'Отзывы на ' + cot_sitename['padeg']['_i'] + ' {{bad-good}}, чем у {{user_percent}} исполнителей в системе.',
				bad: 'хуже',
				good: 'лучше'
			},
			done_orders_percent: {
				text: 'Ответственность {{bad-good}}, чем у {{user_percent}} исполнителей в системе.',
				bad: 'хуже',
				good: 'лучше',
				good100: 'равна или лучше'
			},
			reaction_time: {
				text: 'Время реакции на заказ - {{value}}. Это {{bad-good}}, чем у {{user_percent}} исполнителей.',
				bad: 'медленнее',
				good: 'быстрее',
				zero: 'У вас нет выполненных заказов за {{period}}'
			},
			conversion: {
				text: 'Конверсия ' + cot_sitename['padeg']['_r'] + ' {{bad-good}}, чем у {{user_percent}} исполнителей.',
				bad: 'хуже',
				good: 'лучше'
			},
			work_speed: {
				text: 'Среднее время выполнения заказов составляет {{value}}. Это {{bad-good}}, чем у {{user_percent}} исполнителей.',
				bad: 'медленнее',
				good: 'быстрее'
			}
		};

		return texts[metricName];
	};

	var _showPreloader = function () {
		$_preloader.removeClass('hidden');
	};

	var _hidePreloader = function () {
		$_preloader.addClass('hidden');
	};

	return {
		init: function (userData, period, isNewUser) {
			_period = period;
			_isNewUser = isNewUser;
			$_preloader = $('.js-preloader--analytics');

			_dataCache['statistic'][_period] = userData['statistic'];

			_setStatistic();

			$('.analytics__container').css('opacity', '1');
			_setEvents();
		}
	}
})();