// ***
// *** Functions for XML request management
// ***

/* ************************************************************************** */
/* *** Header declarations ************************************************** */
/* ************************************************************************** */

/* ************************************************************************** */
/* *** Extending standard objects ******************************************* */
/* ************************************************************************** */

XMLHttpRequest.prototype.setParent = function(p) {
	this.parent = p
}

/* ************************************************************************** */
/* *** Custom contents ****************************************************** */
/* ************************************************************************** */

/*
	Constants
  const unsigned short UNSENT = 0
  const unsigned short OPENED = 1
  const unsigned short HEADERS_RECEIVED = 2
  const unsigned short LOADING = 3
  const unsigned short DONE = 4
*/
const MZ = "moz"
const IE = "ie"
/*
	Object for target of XMLHttpRequest
	
	Properties:
		targetUrl
		id
		status
		result
	Methods
		object xmlRequestTarget(key, url)
		void setKey(key)
		string getKey()
		void setUrl(url)
		string getUrl()
*/
function xmlRequestTarget(key, url) {

	this.setKey = function(key) {
		this.id = key
	}

	this.setUrl = function(url) {
		this.targetUrl = url
	}

	this.setUrl(url)
	this.setKey(key)
	this.status = 0 // unsent
	this.result = undefined
	
	this.getUrl = function() {
		return this.targetUrl
	}
	
	this.getKey = function() {
		return this.id
	}

} //xmlRequestTarget

/*
	Object 'xmlRequestManag.er' for managing XMLHttpRequests

	Properties
		passiveMode (boolean)
		items (Array of xmlRequestTarget)
		isMozilla (boolean)
		req (XMLHttpRequest)
		onresult (declaration of function(xmlRequestTarget)
		activeItemIndex
	Methods
		object xmlRequestManager(isPassive = false)
		boolean sendByKey(key)
		integer getFirstOnHoldIndex()
		integer getIndexByKey()
		integer add(xmlRequestTarget)
		boolean startNext()

	Usage:
	
	x = new xmlRequestManager() // init active object
	x.onresult = function(req) {
		// process the result
		...
	}
	x.add(new xmlRequestTarget(key0, url0)) // add targets
	x.add(new xmlRequestTarget(key1, url1)) // ...
	x.add(new xmlRequestTarget(key2, url2))
		
*/
function xmlRequestManager(isPassive) {

	d("xmlRequest: constructor")
	try {
		this.passiveMode = (isPassive === true)
		this.items = new Array()
		this.isMozilla = (window.XMLHttpRequest ? true : false)
		this.req = undefined
		this.onresult = undefined // fnction(xmlRequestTarget)
		this.activeItemIndex = -1
	} catch (e) {
		d("xmlRequest: object init failed: " + e.message)
	}
	
	d("xmlRequest: browser type is " + (this.isMozilla ? "Mozilla" : "IE"))

	this.req = this.isMozilla ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP")
	if (!this.req) {
		d("xmlRequest: XMLHttpRequest init failed")
		return false
	}
	this.req.setParent(this)

	this.sendByKey = function(key) {
		
		if (typeof(this.onresult) != "function") {
			d("xmlRequest: can not start request as 'onresult' is not defined")
			return false
		}
		
		if (false === (i = this.getIndexByKey(key))) {
			d("xmlRequest: Can not find target with key '" + key + "'")
			return false
		} else {
			d("xmlRequest: Making request with key '" + this.items[i].getKey() + "' ... ", false)
			this.activeItemIndex = i
		} // if key is OK
	
		var r = false
	
		this.req.open("GET", this.items[this.activeItemIndex].getUrl(), true)
		
		this.req.onreadystatechange = function() {
			
			if (4 == (this.parent.items[this.parent.activeItemIndex].status = this.parent.req.readyState)) {
				
				d("xmlRequest: Response retrieved. Status = " + this.parent.req.status)
				if (this.parent.req.status == 200 || this.parent.req.status == 304) {
					
					if (!this.parent.isMozilla)
						this.parent.items[this.parent.activeItemIndex].result = new ActiveXObject("Microsodt.XMLDOM")
					this.parent.items[this.parent.activeItemIndex].result = this.parent.req.responseXML
					
				} // status is OK
				
				if (typeof(this.parent.onresult) == "function")
					this.parent.onresult(this.parent.items[this.parent.activeItemIndex])
				else
					d("xmlRequest: can not start result handler. onresult(...) is not a function.")
					
				this.parent.startNext()
			} // if readyState is 4
		} // onreadystatechange
		
		if (this.isMozilla)
			r = this.req.send(null)
		else
			r = this.req.send()
		
		d(r ? "failed" : "ok")

		return r
	} // sendByKey
	
	this.getFirstOnHoldIndex = function() {
		for (var i = 0; i < this.items.length; i++)
			if (this.items[i].status == 0)
				return i
		return false
	} // getFirstOnHoldIndex
	
	this.getIndexByKey = function(key) {
		for (var i = 0; i < this.items.length; i++)
			if (this.items[i].getKey() == key)
				return i
		return false
	} // getIndexByKey
	
	this.add = function(target) {
		this.items.push(target)
		d("xmlRequest: added new target. key = " + target.getKey())
		// Start if there is nothing being processed
		if (this.activeItemIndex == -1)
			this.startNext()
		return this.items.length
	} // add
	
	this.startNext = function() {
		d("xmlRequest: startNext request made", false)
		// if it is in active mode 
		if (this.passiveMode) {
			d("... ups passive mode!")
			return false
		}
		// ... and there is something left to do
		if (false !== (i = this.getFirstOnHoldIndex())) {
			d("... starting with index " + i)
			this.req.abort()
			return this.sendByKey(this.items[i].getKey())
		}
		d("... ups already started or nothing left (i is '" + i + "')")
		return false
	} //startNext
	
	d("xmlRequest: construction done")
	
} // object xmlRequest
