// requires global.js -- NEEDS Function.prototype.closure = function(obj){...} from global.js

/*
Loader / Progress Bar for Google Maps
Author: Jeremy Lazarus
March 1st, 2006
Used on: http://www.motel.com/MapSearch.aspx


Description:
Provides a way to execute processor intensive tasks while not locking up the browser. Also gives the user a true
progress bar and a way to cancel the task.

It works by creating an array of one-time closures for each call. When execute() is called, it begins consuming
small sets of closures and sets a small timeout before executing the next set of closures. The timeout allows
the browser time to process any events, such as rendering and user interaction.

Notes:
Could easily be modified to have pause/resume functionality, if that suits one's needs. Can also adjust the
timeout and steps to execute at once.

Example: (hotels is an array of hotel objects with a show method that takes a boolean argument. show calls map.addOverlay)
var loader = new MLoader(map, document.getElementById("loading"), document.getElementById("loadingText"), document.getElementById("bar"), document.getElementById("fill"), document.getElementById("loadingButton"));

loader.show("Displaying hotels...", true);

for (var i = 0; i < hotels.length; i++)
    loader.add(hotels[i], hotels[i].show, true);

loader.execute();
*/

function MLoader(map, statusElement, textElement, barElement, fillElement, cancelButton)
{

    this.map = map;
    this.statusElement = statusElement;
    this.bar = barElement;
    this.fill = fillElement;
    this.textElement = textElement;
    this.cancelButton = cancelButton;
}
loaderDescription = null;
MLoader.prototype.map = null;
MLoader.prototype.statusElement = null;
MLoader.prototype.textElement = null;
MLoader.prototype.cancelButton = null;
MLoader.prototype.bar = null;
MLoader.prototype.fill = null;
MLoader.prototype.counter = 0;
MLoader.prototype.show = function (text, allowCancel, description)
{
	loaderDescription = description;
    //this.map.disableDragging();
    this.statusElement.style.display = "";
    //this.statusElement.style.left = (document.body.clientWidth - 160)/2 + "px";
    this.textElement.innerHTML = text;

    if (allowCancel)
        this.cancelButton.style.display = "";
    else
        this.cancelButton.style.display = "none";
    this.counter++;
}
MLoader.prototype.hide = function (force)
{
    if (force)
        this.counter = 0;
    else if (this.counter > 0)
        this.counter--;
        
    if (this.counter == 0)
    {
        this.fill.style.width = "1px";
        this.statusElement.style.display = "none";

		//this highlights the particular home. 		
		if (getQueryVariable("homeid")>""  && isFirstQuery) {	
			var selectedHome = getQueryVariable("homeid");
			GEvent.trigger(properties[selectedHome].marker,'click');
		}
		isFirstQuery = false;

        this.map.enableDragging();
		map.showControls();
    }
}
MLoader.prototype.queue = null;
MLoader.prototype.add = function (o, f, a)
{
    if (!this.queue)
        this.queue = new Array();
        
    this.queue[this.queue.length] = _MOneTimeClosure(o,f,a);
}
MLoader.prototype.queueCounter = 0;
MLoader.prototype.execute = function ()
{

    if ((this.queueCounter > 0) && (this.queue))
        this.fill.style.width = (100 * this.queueCounter / this.queue.length) + "%";
    else
        this.fill.style.width = "1px";
    
	if (this.queue) document.getElementById("loadingText").innerHTML = "Loading " + this.queueCounter + " of " + this.queue.length + " " + loaderDescription;

    var stopAt = this.queueCounter + 20;
    while ((this.queue) && (this.queueCounter < this.queue.length) && (this.queueCounter < stopAt))
    {
        this.queue[this.queueCounter]();
        this.queue[this.queueCounter++] = null;
    }
    
    if ((this.queue) && (this.queueCounter < this.queue.length))
    {
        setTimeout(this.execute.closure(this), 500);
    }
    else
    {
        for (var i = 0; (this.queue) && (i < this.queue.length); i++)
            this.queue[i] = null;
        this.queue = null;
        this.queueCounter = 0;
        this.hide(true);
    }
}
MLoader.prototype.cancel = function ()
{
    for (var i = 0; (this.queue) && (i < this.queue.length); i++)
        this.queue[i] = null;
    this.queue = null;
    this.queueCounter = 0;
    this.hide(true);
}

// Executes once and removes all references
function _MOneTimeClosure (h, f, a){
        return (function() {
            h.f = f;
            h.f(a);
            a = null;
            h.f = null;
            h = null;
        })
    }