// $Id: window-states-modes.js 4432 2006-09-14 07:45:55Z shacka $
/**
 *
 * Copyright (c) 2006 by SouthProjects
 * http://www.southprojects.com
 * Santiago, Chile,
 * Version 1.2 Dec 2006.
 * All rights reserved.
 */

/**
 * Sets the widgets privillage mode to on.
 * @param mode [string] - mode to set.
 */
southprojects.Window.prototype.setModeOn = function(mode) {
	if (typeof mode != "string") {
		return false;
	}
	if (!this.widgetModes[mode]) {
		this.widgetModes[mode] = {};
	}
	this.widgetModes[mode].on = true;
	this.widgetModes[mode].caller = this.setModeOn.caller;
	this.fireEvent(mode + "_on", this);
	return true;
};

/**
 * Sets the widgets privillage mode to off.
 * @param mode [string] - mode to set.
 */
southprojects.Window.prototype.setModeOff = function(mode) {
	if (typeof mode != "string" || !this.widgetModes[mode]) {
		return false;
	}
	this.widgetModes[mode].on = false;
	this.widgetModes[mode].caller = null;
	this.fireEvent(mode + "_off", this);
	return true;
};

/** 
 * Returns true if the mode is on, otherwise false
 * @param mode [string] - mode to check
 * @return true if the mode is on, otherwise false
 */
southprojects.Window.prototype.modeOn = function(mode) {
	if (this.widgetModes[mode] && this.widgetModes[mode].on === true) {
		return true;
	}
	return false;
};

/**
 * Returns true if called function was called from the method that set the mode.
 * @param mode [string] - mode to check
 * @param caller [function] - called function.
 * @return returns true if called function was called from the method that set the mode.
 */
southprojects.Window.prototype.modeSameCaller = function(mode, caller) {
	while(caller) {
		if (caller.caller == this.widgetModes[mode].caller) {
			return true;
		}
		caller = caller.caller;
	}
	return false;
};

/**
 * Checks if needed state was reached and tryes to fire function exactly when it needs.
 * @param state [string] - required state;
 * @param func [function] - function needed to be fired
 * @param first [boolean] - should it go first
 * @return true if the state was already reached
 */
southprojects.Window.prototype.fireOnState = function(state, func) {
	if (this.modeOn("immediate_execution") && this.modeSameCaller("immediate_execution", this.fireOnState)) {
		return true;
	}
	if (state == "body_loaded") {
		if (!this.stateReached("created")) {
			return false;
		}
		if (!southprojects.windowLoaded) {
			setTimeout(func, 50);
			return false;
		}
		
		return true;
	}
	if (!this.stateReached(state)) {
		if (!this.stateReached("created")) {
			return false;
		}
		
		if (this.modeOn("privileged_execution") && this.modeSameCaller("privileged_execution", this.fireOnState)) {
			this.highPriorityEvents.push({"state" : state, "listener" : func, "executed" : false});
			return false;
		}	
		if (this.modeOn("delayed_execution")) {
			this.delayedEvents.push({"state" : state, "listener" : func});
			return false;
		}
		this.addEventListener(state, func);
		
		return false;
	} else {
		return true;
	}
};

/**
 * Changes the state of the widget, firing all the events planned
 * @param state [string] - state to set.
 * @return true if succeeds, otherwise false
 */
southprojects.Window.prototype.changeState = function(state) {
	var self = this;
	if (this.modeOn("delayed_execution")) {
		this.addEventListener("delayed_execution_off", function() {self.changeState(state);});
	}
	if (this.modeOn("privileged_execution")) {
		this.setModeOff("privileged_execution");
	}
	this.widgetState = state;
	if (!this.events[state]) {
		return;
	}
	for(var ii = 0; ii < this.events[state].listeners.length; ++ii) {
		if (!this.modeOn("delayed_execution")) {
			this.events[state].listeners[ii].apply(this);
			//alert(this.events[state].listeners[ii] + " \n " + this.modeOn("delayed_execution"));
		} else {
			this.addEventListener("delayed_execution_off", this.events[state].listeners[ii]);
		}
	}
	this.events[state] = null;
	return true;
} 

/**
 * This method tells you wether the state you need was reached or maybe already passed.
 * Right now we have following states:
 * 'destroyed' - the object was destroyed;
 * 'created' - the instance of the object was created;
 * 'inited' - the object was inited (this include initing all variables, calling parent
 *            init and starting loading structure);
 * 'loaded' - the structure is loaded and parsed;
 * 'ready' - object has all the parts ready for work;
 * 'hidden' - object is visually hidden;
 * 'shown' - object is visible;
 * @param state [string] - the name of the state you need to check;
 * @return - true if the state was reached or already passed, otherwise false
 */
southprojects.Window.prototype.stateReached = function(state) {
	//getting current state priority.
	//if there is no such in our priority array we give it the highest priority, 
	//which means count of states avaliable in the array.
	var currentState = this.priorities[this.widgetState] || (this.priorities[this.widgetState] !== 0 ? this.priorities.count : 0);
	//getting passed state priority.
	//if there is no such in our priority array we give it the highest priority, 
	//which means count of states avaliable in the array.
	var state = this.priorities[state] || (this.priorities[state] !== 0 ? this.priorities.count : 0);
	//and now compareing them
	if (state > currentState) return false;
	return true;
};
