/**
 * Arrays
 */
function __array_shuffle() {
	var new_arr = new Array();
	
	for(i=this.length; i>0; i--) {
		new_arr[i-1] = this.splice(Math.random2(i), 1);
	}
	
	return new_arr;
}

Array.prototype.shuffle = __array_shuffle;

function __array_has_value(value) {
	for(var i in this) {
		if (this[i] == value)
			return i;
	}
	
	return false;
}

Array.prototype.hasValue = __array_has_value;

Array.urandom = function(n, max) {
	var arr = [];
	
	for(i=0; i<n; i++) {
		var rnd = null;
		
		do {
			rnd = Math.random2(max);
		} while(arr.hasValue(rnd));
		
		arr.push(rnd);
	}
	
	return arr;
}

Array.create = function(start, count) {
	var arr = new Array(count);
	
	for(var i=0; i<count; i++) arr[i] = (i+start);
	
	return arr;
}

Math.random2 = function(max) {
	return Math.round(Math.random()*1000)%max;
}

function load_images_list(filename) {
	var content = load_file(filename, false);
	
	if (content)
		return content.split("\r\n");
		
	return [];
}

/**
 * Plate
 */
function Plate(img) {
	this.current = img;
	this.locked = false;
	this.next = new Image();
	this.opacity = 1;
	this.queue = null;
}

Plate_name = function(id) {
	return "__img" + id;
}

Plate.prototype.setOpacity = function(opacity) {
	this.opacity = opacity;
	this.getCurrent().style.opacity = opacity;
	this.getCurrent().style.filter = "alpha(opacity=" + (opacity * 100) + ")";
}

Plate.prototype.getOpacity = function() {
	return this.opacity;
}

Plate.prototype.setCurrent = function(src) {
	this.getCurrent().src = src;
}

Plate.prototype.getCurrent = function() {
	return this.current;
}

Plate.prototype.setNext = function(next_src) {
	this.getNext().src = next_src;
}

Plate.prototype.getNext = function() {
	return this.next;
}

Plate.prototype.change = function(next) {
	this.getCurrent().src = this.getNext().src;
	this.setNext(next);
}

/**
 * Effect (abstract)
 */
function Effect(playground) {
	this.playground = playground;
}

Effect.prototype.getPlayground = function() {
	return this.playground;
}

Effect.prototype.init = function() {
	// do nothing
}

Effect.prototype.play = function() {
	// do nothing
}

Effect.prototype.setPlayground = function(playground) {
	this.playground = playground;
}

/**
 * Playground
 */
function Playground(box, width, height, pwidth, pheight, margin) {
	this.box = box;
	this.effect = null;
	this.height = height;
	this.margin = margin;
	this.plates = new Object();
	this.plate_height = pheight;
	this.plate_width = pwidth;
	this.width = width;
}

Playground.prototype.init = function() {
	var root = document.getElementById(this.box);
	
	for(i=0; i<this.height; i++) {
		for(j=0; j<this.width; j++) {
			var div = document.createElement("div");
			div.style.position = "absolute";
			div.style.top = ((i*this.plate_height) + (i*this.margin) + 1) + "px";
			div.style.left = ((j*this.plate_width) + (j*this.margin) + 1) + "px";
			var plate = this.addPlate( (i*this.width) + j );
			div.appendChild(plate.getCurrent());
			root.appendChild(div);
		}
	}
}

Playground.prototype.addPlate = function(id, src) {
	if (this.plateExist(id)) {
		this.plates[id].setCurrent(src);
	} else {
		var img = new Image(this.plate_width, this.plate_height);
		img.src = src;
		img.id = Plate_name(id);
		this.plates[id] = new Plate(img);
	}
	
	return this.plates[id];
}

Playground.prototype.getPlate = function(id) {
	if (this.plateExist(id)) {
		return this.plates[id];
	}
	
	return null;
}

Playground.prototype.plateExist = function(id) {
	return (this.plates[id] instanceof Plate ? true : false);
}

Playground.prototype.setEffect = function(effect) {
	if (effect instanceof Effect) {
		this.effect = effect;
	}
}

Playground.prototype.run = function() {
	this.init();
	this.effect.play();
}

/**
 * Interval Queue
 *
 * Expressions beginning with __ should NOT be using by programmer!
 */
var __iq_queues = [];

function __iq_queue(end_method, instance, params, delay) {
	this.end = (instance == null ? null : new __iq_entry(end_method, instance, params, delay));
	this.delay = delay;
	this.interval = null;
	this.items = [];
}

function __iq_entry(funct, inst, params, time) {
	this.func = funct;
	this.instance = inst;
	this.params = params;
	this.time = time;
}

function iq_create(end_method, instance, params, delay) {
	return (__iq_queues.push(new __iq_queue(end_method, instance, params, delay || 0)) - 1);
}

function iq_add(queue_id, func, inst, params, time) {
	__iq_queues[queue_id].items.push(new __iq_entry(func, inst, params, time));
	
	if (__iq_queues[queue_id].interval == null) __iq_run(queue_id);
}

function __iq_clear_interval(queue_id) {
	if (__iq_queues[queue_id].interval != null) {
		clearInterval(__iq_queues[queue_id].interval);
		__iq_queues[queue_id].interval = null;
	}
}

function __iq_timeout_proc(queue_id) {
	var end = __iq_queues[queue_id].end;
	end.func.apply(end.instance, end.params);
}

function __iq_run(queue_id) {
	var queue = __iq_queues[queue_id];
	
	if (queue.items.length) {
		if (queue.interval == null) {
			queue.interval = setInterval("__iq_run("+queue_id+")", queue.items[0].time);
		}
		
		var item = queue.items[0];
		if (!item.func.apply(item.instance, item.params)) {
			queue.items.shift();
			__iq_clear_interval(queue_id);
			__iq_run(queue_id);
		}
	} else if (queue.end != null) {
		setTimeout("__iq_timeout_proc(" + queue_id + ")", queue.end.time); // "__iq_queues["+queue_id+"].end()", queue.delay); // hmmm...
	}
}

/**
 * Events
 */
function __Event(func, inst, params) {
	this.func = func;
	this.inst = inst;
	this.params = params;
}

function __run_event(event) {
	var e = (window.event ? event.srcElement : event.target);
	var ee = e['e'+event.type];
	ee.func.apply(ee.inst, ee.params);
}

var Event = {
	add: function(obj, type, func, inst, params) {
		obj['e'+type] = new __Event(func, inst, params);
		
		if (obj.attachEvent) {
			obj.attachEvent("on"+type, __run_event);
		} else {
			obj.addEventListener(type, __run_event, false);
		}
	},
	
	remove: function(obj, type) {
		obj['e'+type] = null;
		
		if (obj.detachEvent) {
			obj.detachEvent("on"+type, __run_event);
		} else {
			obj.removeEventListener(type, __run_event, false);
		}
	}
}

/**
 *
 */
function create_path(dir, file) {
	return "gfx/" + dir + "/" + file + ".jpg";
}

