/*
======================================================================
JavaScript ContentRetriever class
Author: Alessandro Lacava http://www.alessandrolacava.com
Created: Jul 25th, 2006.
Description: Retrieve the content from a URL that returns JSON text. 
Afterward it builds the HTML code to return to the Observers.
The HTML is built using the HtmlBuilder class defined within
htmlBuilder.js. This way I separate the logic used to retrieve the
JSON string from the logic used to build the HTML code.
The HtmlBuilder class returns the HTML code as a 
JavaScript array which is what the Observers expect.
The Observers are notified calling the update() function on them
and passing the aforementioned array.
Note: This class uses a method defined in another file. The method
is createHttpRequest() that is in the ajax.js file.
======================================================================
*/

// ContentRetriever class
function ContentRetriever(jsonDataRetriever, observerObjectsArray)
{
	// JSON data retrieved and parsed
	this.jsonData = "";
	// Server-side component URL responsible to retrieve the JSON data
	this.jsonDataRetriever = jsonDataRetriever;
	// AJAX object
	this.ajaxObj = createHttpRequest();
	// Reference to the observer objects array
	this.observerObjectsArray = observerObjectsArray;
}

// AJAX call used to get the content in a JSON format
ContentRetriever.prototype.getContent = function()
{
	if (this.ajaxObj)
	{
		var instance = this;
		this.ajaxObj.open('GET', this.jsonDataRetriever, true);
		//callback function
		this.ajaxObj.onreadystatechange = function(){instance.processDataRetrieved();};
		this.ajaxObj.send(null);
	}
};

//callback function
ContentRetriever.prototype.processDataRetrieved = function()
{
	//request completed
	if (this.ajaxObj.readyState == 4)
	{ 
		//request succeeded
		if (this.ajaxObj.status==200)
		{ 
			//check the emptiness of the response
			if(this.ajaxObj.responseText != null && this.ajaxObj.responseText.length > 0)
			{
				var htmlBuilder = new HtmlBuilder(this.ajaxObj.responseText);
				//parse the JSON data
				this.jsonData = htmlBuilder.getHtml();
			}
			else
			{
				//return a zero-length array if an error occurs
				this.jsonData = [];
			}
			// notify observers
			this.notify();
		}
	}
};

//notify all observers
ContentRetriever.prototype.notify = function()
{
	//call the observers' callback function passing in the resulting array
	for(var i = 0; i < this.observerObjectsArray.length; i++)
	{
		this.observerObjectsArray[i].update(this.jsonData);
	}
};	

//append an observer
ContentRetriever.prototype.attach = function(observerObject)
{
	this.observerObjectsArray.push(observerObject);
};

//remove an observer
ContentRetriever.prototype.detach = function(observerObject)
{
	if(this.observerObjectsArray == null || this.observerObjectsArray.length == 0)
	{
		return;
	}
	var index = this.findIndexOf(observerObject);
	if(index != -1)
	{
		this.detachAt(index);
	}
};


/* 
	 THE FOLLOWING FUNCTIONS ARE USED INTERNALLY TO FIND THE
	 INDEX OF A DETERMINED OBSERVER AND REMOVE IT FROM THE OBSERVERS ARRAY
*/

//find the index of an observer within the observer array
ContentRetriever.prototype.findIndexOf = function(observerObject) 
{
  for (var i = 0; i < this.observerObjectsArray.length; ++i)
  {
    if (this.observerObjectsArray[i] == observerObject)
    {
      return i;
    }
  }
  //not found
  return -1;
};

//remove an element from the observer array
ContentRetriever.prototype.detachAt = function(index)
{
  var length = this.observerObjectsArray.length;
  if (length  == 0)
  {
    return;
  }

  switch(index)
  {
  case -1:
  	//invalid
    break;
  case 0:
  	//remove the first element
    this.observerObjectsArray.shift();
    break;
  case length - 1:
  	//remove the last element
    this.observerObjectsArray.pop();
    break;
  default:
  	//split the array in two, leaving out the element at the index "index" and then rejoin them as one array
    var head = this.observerObjectsArray.slice(0, index);
    var tail = this.observerObjectsArray.slice(index+1);
    this.observerObjectsArray = head.concat(tail);
    break;
  }
};	
