'use strict';

var isArray = require('./helpers').isArray;
var isPattern = require('./helpers').isPattern;
var getPattern = require('./helpers').getPattern;

function groupDecorations(line) {
	var groups = [], currentGroup = null;
	for (var i = 0, l = line.inlines.length; i < l; i++) {
		var inline = line.inlines[i];
		var decoration = inline.decoration;
		if (!decoration) {
			currentGroup = null;
			continue;
		}
		if (!isArray(decoration)) {
			decoration = [decoration];
		}
		var color = inline.decorationColor || inline.color || 'black';
		var style = inline.decorationStyle || 'solid';
		for (var ii = 0, ll = decoration.length; ii < ll; ii++) {
			var decorationItem = decoration[ii];
			if (!currentGroup || decorationItem !== currentGroup.decoration ||
				style !== currentGroup.decorationStyle || color !== currentGroup.decorationColor) {

				currentGroup = {
					line: line,
					decoration: decorationItem,
					decorationColor: color,
					decorationStyle: style,
					inlines: [inline]
				};
				groups.push(currentGroup);
			} else {
				currentGroup.inlines.push(inline);
			}
		}
	}

	return groups;
}

function drawDecoration(group, x, y, pdfKitDoc) {
	function maxInline() {
		var max = 0;
		for (var i = 0, l = group.inlines.length; i < l; i++) {
			var inline = group.inlines[i];
			max = inline.fontSize > max ? i : max;
		}
		return group.inlines[max];
	}
	function width() {
		var sum = 0;
		for (var i = 0, l = group.inlines.length; i < l; i++) {
			var justifyShift = (group.inlines[i].justifyShift || 0);
			sum += group.inlines[i].width + justifyShift;
		}
		return sum;
	}
	var firstInline = group.inlines[0],
		biggerInline = maxInline(),
		totalWidth = width(),
		lineAscent = group.line.getAscenderHeight(),
		ascent = biggerInline.font.ascender / 1000 * biggerInline.fontSize,
		height = biggerInline.height,
		descent = height - ascent;

	var lw = 0.5 + Math.floor(Math.max(biggerInline.fontSize - 8, 0) / 2) * 0.12;

	switch (group.decoration) {
		case 'underline':
			y += lineAscent + descent * 0.45;
			break;
		case 'overline':
			y += lineAscent - (ascent * 0.85);
			break;
		case 'lineThrough':
			y += lineAscent - (ascent * 0.25);
			break;
		default:
			throw 'Unknown decoration : ' + group.decoration;
	}
	pdfKitDoc.save();

	if (group.decorationStyle === 'double') {
		var gap = Math.max(0.5, lw * 2);
		pdfKitDoc.fillColor(group.decorationColor)
			.rect(x + firstInline.x, y - lw / 2, totalWidth, lw / 2).fill()
			.rect(x + firstInline.x, y + gap - lw / 2, totalWidth, lw / 2).fill();
	} else if (group.decorationStyle === 'dashed') {
		var nbDashes = Math.ceil(totalWidth / (3.96 + 2.84));
		var rdx = x + firstInline.x;
		pdfKitDoc.rect(rdx, y, totalWidth, lw).clip();
		pdfKitDoc.fillColor(group.decorationColor);
		for (var i = 0; i < nbDashes; i++) {
			pdfKitDoc.rect(rdx, y - lw / 2, 3.96, lw).fill();
			rdx += 3.96 + 2.84;
		}
	} else if (group.decorationStyle === 'dotted') {
		var nbDots = Math.ceil(totalWidth / (lw * 3));
		var rx = x + firstInline.x;
		pdfKitDoc.rect(rx, y, totalWidth, lw).clip();
		pdfKitDoc.fillColor(group.decorationColor);
		for (var ii = 0; ii < nbDots; ii++) {
			pdfKitDoc.rect(rx, y - lw / 2, lw, lw).fill();
			rx += (lw * 3);
		}
	} else if (group.decorationStyle === 'wavy') {
		var sh = 0.7, sv = 1;
		var nbWaves = Math.ceil(totalWidth / (sh * 2)) + 1;
		var rwx = x + firstInline.x - 1;
		pdfKitDoc.rect(x + firstInline.x, y - sv, totalWidth, y + sv).clip();
		pdfKitDoc.lineWidth(0.24);
		pdfKitDoc.moveTo(rwx, y);
		for (var iii = 0; iii < nbWaves; iii++) {
			pdfKitDoc.bezierCurveTo(rwx + sh, y - sv, rwx + sh * 2, y - sv, rwx + sh * 3, y)
				.bezierCurveTo(rwx + sh * 4, y + sv, rwx + sh * 5, y + sv, rwx + sh * 6, y);
			rwx += sh * 6;
		}
		pdfKitDoc.stroke(group.decorationColor);
	} else {
		pdfKitDoc.fillColor(group.decorationColor)
			.rect(x + firstInline.x, y - lw / 2, totalWidth, lw)
			.fill();
	}
	pdfKitDoc.restore();
}

function drawDecorations(line, x, y, pdfKitDoc) {
	var groups = groupDecorations(line);
	for (var i = 0, l = groups.length; i < l; i++) {
		drawDecoration(groups[i], x, y, pdfKitDoc);
	}
}

function drawBackground(line, x, y, patterns, pdfKitDoc) {
	var height = line.getHeight();
	for (var i = 0, l = line.inlines.length; i < l; i++) {
		var inline = line.inlines[i];
		if (!inline.background) {
			continue;
		}
		var color = inline.background;
		if (isPattern(inline.background)) {
			color = getPattern(inline.background, patterns);
		}
		var justifyShift = (inline.justifyShift || 0);
		pdfKitDoc.fillColor(color)
			.rect(x + inline.x - justifyShift, y, inline.width + justifyShift, height)
			.fill();
	}
}

module.exports = {
	drawBackground: drawBackground,
	drawDecorations: drawDecorations
};
