////////////////////////////////////////////////////////////////////////////////
// Note from the Scriptographer.org Team
//
// In Scriptographer 2.9, we switched to a top-down coordinate system and
// degrees for angle units as an easier alternative to radians.
// 
// For backward compatibility we offer the possibility to still use the old
// bottom-up coordinate system and radians for angle units, by setting the two
// values bellow. Read more about this transition on our website:
// http://scriptographer.org/news/version-2.9.064-arrived/

script.coordinateSystem = 'bottom-up';
script.angleUnits = 'radians';

// raster.js is a base script for all the raster scripts
// that take a selection of a raster and a path object
// as a starting point for some raster processing
// the only thing that has to be defined is the drawDot 
// function
var raster = null, dots = [], pixelCount;

Item.prototype.getCompoundArea = function(area) {
	if (!area) area = 0;
	if (this instanceof Path) return area + this.area;
	else if (this instanceof CompoundPath || this instanceof Group) {
		var child = this.firstChild;
		while (child) {
			area = child.getCompoundArea(area);
			child = child.nextSibling;
		}
	}
	return area;
};

function initRaster() {
	var error = false;
	if (!document) {
		Dialog.alert('Please open a document first.');
		return false;
	}
	
	var rasters = document.getSelectedItems([Raster, PlacedFile]);
	for (var i = 0, l = rasters.length; i < l; i++) {
		rasters[i].selected = false;
	}
	
	var sel = document.selectedItems;
	
	if(rasters.length) {
		raster = rasters.first;
		if(raster instanceof PlacedFile && !raster.eps) {
			// Embed placed images so the raster script can access pixels
			raster = raster.embed(false);
		}
		
		for (var i = 0; i < sel.length; i++) {
			var obj = sel[i];
			if(!obj.isAncestor(raster))
				dots.push(obj);
		}
	}
	
	if (!raster || !dots.length) {
		Dialog.alert('Please select both a raster item\nand a graphic item.');
		return false;
	} else {
		pixelCount = raster.height * raster.width;
		var sure = true;
		if(pixelCount > 20000) {
			script.showProgress = false;
			sure = Dialog.confirm('The image you\'re about to rasterize contains ' + pixelCount + ' pixels.\nRasterizing could take a long time.\nAre you sure you want to proceed?');
			script.showProgress = true;
		}
		return sure;
	}
}

function executeRaster(createDot, multiple) {
	document.deselectAll();
	var group = new Group();
	for (var i = 0; i < dots.length; i++) {
		// Create a copy of each dot that is moved to the origin so 
		// rasters that scale the dot are simple to realize:
		var dot = dots[i] = dots[i].clone();
		var origin = dot.bounds.center;
		dot.position -= origin;
		// Scale multiple dots to the same blackness as the first one
		if (multiple && i > 0)
			dot.scale(Math.sqrt(Math.abs(dots[0].getCompoundArea()) / Math.abs(dot.getCompoundArea())));
	}

	for (var y = 0; y < raster.height; y++) {
		for (var x = 0; x < raster.width; x++) {
			illustrator.updateProgress(y * raster.width + x + 1, pixelCount);
			var color = raster.getPixel(x, y);
			var radius = color.gray;
			var obj = createDot(x, raster.height - y, multiple ? dots : dots[0], color, radius);
			if (obj) {
				obj.position += origin;
				group.appendChild(obj);
			}
		}
		document.redraw();
	}
	for (var i = 0; i < dots.length; i++)
		dots[i].remove();
	return group;
}

function setColor(art, color) {
	if (art instanceof Path) {
		if (art.style.stroke.color != null) art.style.stroke.color = color;
		if (art.style.fill.color != null) art.style.fill.color = color;
	}
	var child = art.firstChild;
	while (child != null) {
		setColor(child, color);
		child = child.nextSibling;
	}
}

function createDot(x, y, dot, color, radius) {
	if (radius > 0.1) {
		var item = dot.clone();
		item.position += new Point(x, y) * values.size;
		item.scale(radius * values.scale);
		setColor(item, color);
		return item;
	}
}

if (initRaster()) {
	var values = Dialog.prompt('Enter Raster Values:', {
		size: { value: 10, description: 'Grid Size'},
		scale: { value: 100, description: 'Object Scale (%)'}
	});
	if (values) {
		values.scale /= 100;
		executeRaster(createDot);
	}
}
