#!/usr/bin/env node

// Copyright 2014-2015 Yahoo! Inc.
// Copyrights licensed under the Mit License. See the accompanying LICENSE file for terms.

var BlinkDiff = require('../index2');
var Compatibility = require('../lib/compatibility');

try {

	printLicense();

	var options = parseArgs(process.argv.slice(1));

	var compatibility = new Compatibility(options);

	var diff = new BlinkDiff(compatibility.generate());
	if (options.verbose) {
		diff.verbose = true;
	}

	// Setup console logger
	diff.log = function (text) {
		if (this.verbose) {
			console.log(text);
		}
	};

	if (diff.verbose) {
		console.time('Time');
	}
	var result = diff.process();

	var passed = diff.hasPassed(result.code);

	if (diff.verbose) {
		console.timeEnd('Time');

		console.log('Differences:', result.differences, '(' + Math.round((result.differences / result.dimension) * 10000) / 100 + '%)');
	}

	if (passed) {
		if (diff.verbose) {
			console.log("PASS");
		}
	} else {
		console.log("FAIL");
	}

	process.exit(passed ? 0 : 1);

} catch (exception) {
	console.error(exception.message);
	process.exit(1);
}

/**
 * Prints the license
 */
function printLicense () {
	console.log("Blink-Diff " + BlinkDiff.version);
	console.log("Copyright (C) 2014 Yahoo! Inc.");
}

/**
 * Prints the help info
 */
function printHelp () {
	console.log("Usage: blink-diff <image1> <image2>");
	console.log("");
	console.log("  Compares image1 and image2.");
	console.log("");
	console.log("  Options:");
	console.log("    --verbose           Turn on verbose mode");
	console.log("    --debug             Turn on debug mode - leaving all filters and modifications on the result");
	console.log("    --threshold p       Number of pixels/percent 'p' below which differences are ignored");
	console.log("    --threshold-type t  'pixel' and 'percent' as type of threshold. (default: pixel)");
	console.log("    --delta p           Max. distance colors in the 4 dimensional color-space without triggering a difference. (default: 20)");
	console.log("    --copyImageA        Copies first image to output as base. (default: true)");
	console.log("    --copyImageB        Copies second image to output as base.");
	console.log("    --no-copy           Doesn't copy anything to output as base.");
	console.log("    --output o          Write difference to the file 'o'");
	console.log("    --filter f          Filters f (separated with comma) that will be applied before the comparison.");
	console.log("    --no-composition    Turns the composition feature off");
	console.log("    --compose-ltr       Compose output image from left to right");
	console.log("    --compose-ttb       Compose output image from top to bottom");
	console.log("    --hide-shift        Hides shift highlighting (default: false)");
	console.log("    --h-shift           Acceptable horizontal shift of pixel. (default: 0)");
	console.log("    --v-shift           Acceptable vertical shift of pixel. (default: 0)");
	console.log("    --block-out x,y,w,h Block-out area. Can be repeated multiple times.");
	console.log("    --version           Print version");
	console.log("    --help              This help");
	console.log("");
}

/**
 * Parses the arguments and returns an option list
 *
 * @param {string[]} argv
 * @return {object}
 */
function parseArgs (argv) {

	var i, temporary, imageCount = 0, argLength = argv.length, options = {};

	if (argLength <= 1) {
		printHelp();
		process.exit(1);
	}

	options.blockOut = [];

	for (i = 1; i < argLength; i++) {

		try {

			if (argv[i] == "--help") {
				printHelp();
				process.exit(0);

			} else if (argv[i] == "--verbose") {
				options.verbose = true;

			} else if (argv[i] == "--debug") {
				options.debug = true;

			} else if (argv[i] == "--no-composition") {
				options.composition = false;

			} else if (argv[i] == "--compose-ltr") {
				options.composeLeftToRight = true;

			} else if (argv[i] == "--compose-ttb") {
				options.composeTopToBottom = true;

			} else if (argv[i] == "--no-copy") {
				options.copyImageAToOutput = false;
				options.copyImageBToOutput = false;

			} else if (argv[i] == "--hide-shift") {
				options.hideShift = true;

			} else if (argv[i] == "--copyImageA") {
				options.copyImageAToOutput = true;
				options.copyImageBToOutput = false;

			} else if (argv[i] == "--copyImageB") {
				options.copyImageAToOutput = false;
				options.copyImageBToOutput = true;

			} else if (argv[i] == "--threshold-type") {
				if (++i < argLength) {
					if (argv[i] === 'pixel') {
						options.thresholdType = BlinkDiff.THRESHOLD_PIXEL;

					} else if (argv[i] === 'percent') {
						options.thresholdType = BlinkDiff.THRESHOLD_PERCENT;

					} else {
						throw new Error("--threshold-type can be either 'pixel' or 'percent'");
					}
				}

			} else if (argv[i] == "--threshold") {
				if (++i < argLength) {

					temporary = parseFloat(argv[i]);
					if (temporary < 0) {
						throw new Error("--threshold must be positive");
					}
					options.threshold = temporary;
				}

			} else if (argv[i] == "--h-shift") {
				if (++i < argLength) {

					temporary = parseInt(argv[i], 10);
					if (temporary < 0) {
						throw new Error("--h-shift must be positive");
					}
					options.hShift = temporary;
				}

			} else if (argv[i] == "--v-shift") {
				if (++i < argLength) {

					temporary = parseInt(argv[i], 10);
					if (temporary < 0) {
						throw new Error("--v-shift must be positive");
					}
					options.vShift = temporary;
				}

			} else if (argv[i] == "--delta") {
				if (++i < argLength) {

					temporary = parseFloat(argv[i]);
					if (temporary < 0) {
						throw new Error("--delta must be positive");
					}
					options.delta = temporary;
				}

			} else if (argv[i] == "--block-out") {
				if (++i < argLength) {

					temporary = argv[i].split(',');
					if (temporary.length < 2) {
						throw new Error("--block-out should at least have the x and y coordinate");
					}
					options.blockOut.push({
						x: parseInt(temporary[0], 10),
						y: parseInt(temporary[1], 10),
						width: parseInt(temporary[2], 10),
						height: parseInt(temporary[3], 10)
					});
				}

			} else if (argv[i] == "--filter") {
				if (++i < argLength) {
					options.filter = argv[i].split(',');
				}

			} else if (argv[i] == "--output") {
				if (++i < argLength) {
					options.imageOutputPath = argv[i];
				}

			} else if (argv[i] == "--version") {
				console.log("Blink-Diff " + BlinkDiff.version);

			} else if (imageCount < 2) {

				++imageCount;
				if (imageCount == 1) {
					options.imageAPath = argv[i];
				} else {
					options.imageBPath = argv[i];
				}

			} else {
				console.log('Warning: parameter "' + argv[i] + '" ignored. Unknown.');
			}

		} catch (exception) {
			var reason = (exception.message !== '') ? "; " + exception.message : '';
			throw new Error("Invalid argument '" + argv[i] + "' for " + argv[i - 1] + reason);
		}
	}

	if (!options.imageAPath || !options.imageBPath) {
		throw new Error("Please specify two images.");
	}

	return options;
}