// Delays the call of the supplied function until the window is loaded.
var $_ = function(fn /* ... */) {
    var args = Array.prototype.slice.call(arguments, 1)
    Event.observe(window, "load", function(evt) {
        fn.apply(this, args)
    });
}

// This function gives focus to the first focusable field in the first form of a page.
var initializeFocus = function() {
    var forms   = $$("form");
    var form    = forms.pop();

    if(form) {
    
        // Get all inputs (excluding hidden), selects, textareas and buttons.
        var elements = form.select("input:not([type=hidden])", "select", "textarea", "button");
        for(var i=0, n=elements.length; i<n; i++) {
            try {
                elements[i].focus();
                break;
            } catch(e) {
                // do nothing
            }
        }
    }
}

// Removes the borders from the elements specified by the selector
var removeBorders = function(selector) {
    $$(selector).each(function(e) {
       e.style.border = "none"; 
    });
}

var replaceIds = function(s) {
    return s.replace(/NEW_RECORD/g, new Date().getTime());
}

// This is the namespace for all of our delegation rulesets.
var delegationRules = {
    
    // This function allows us to submit a fields form upon some event.
    submitForm: function(evt) {
        var element = Event.findElement(evt);
        var form    = element.up("form");
         if(form) {
            form.submit();
        }
    },

	// This function switches the main property photo when a thumbnail is clicked.
	clickThumb: function(evt) {
		var main  = $("PropertyDetailMainContainer")
		var thumb = Event.findElement(evt);
		if (main && main.style && thumb && thumb.src) {
			var src = thumb.src.replace("_back_listing", "_front_detail");
			main.style.backgroundImage = "url(" + src + ")";
		}
	},
	
	showTogglebox: function(evt, show) {
	    evt.stop();
	    var element = Event.findElement(evt);
	    if(element) {
	        togglebox.setIsShowing(element.up(".togglebox"), show);
	    }
	}
}

// These are the rules used to handle change events on an element.
delegationRules.change = {
    
    // This rule submits the search by state form when its selector changes.
    "#state_prov":                   delegationRules.submitForm,
    
    // This rule submits the filter form when any of its selectors change.
    "#PropertyListFilters select":   delegationRules.submitForm
}

// These are the rules used to handle click events on an element.
delegationRules.click = {
    
    // ------------------------------------------------------------------------
    // Dynamic form rules
    // ------------------------------------------------------------------------
    
    ".remove img": function(evt) {
        var el      = Event.findElement(evt);
        var link    = el.up();
        var target  = link.href.replace(/.*#/, ".");
        
        var hiddenInput = link.previous("input[type=hidden]");
        if(hiddenInput) {
            link.up(target).hide();
            hiddenInput.value = 1;
        } else {
            link.up(target).remove();
        }
    },
    
    ".add_nested_item": function(evt) {
        var el          = Event.findElement(evt);
        var template    = window[el.href.replace(/.*#/, "")];
        var container   = $(el.rel);
        
        container.insert({     
          bottom: replaceIds(template)
        });
        
        WithLabel.init(container.lastChild);
    },
    
	// This rule flips the main photo when a thumb is clicked
	".photos .thumbs img": 			delegationRules.clickThumb,
	
	".toggleboxTitleShow": function(evt) {
	    delegationRules.showTogglebox(evt, true);
	},
	
	".toggleboxTitleHide": function(evt) {
	    delegationRules.showTogglebox(evt, false);
	}
}

/**
 * This ruleset handles mouse over events.
 */
delegationRules.over = {
    
    // Primary nav rollover
    "#PageHeaderPrimaryNav a img": function(evt) {
        var element = Event.findElement(evt);
        if(element && !element.id.match(/.*_active?/)) {
            element.src = "/images/" + element.id + "_over.gif";
        }
    }
}

/**
 * This ruleset handles mouse out events.
 */
delegationRules.out = {
    
    // Primary nav rollover
    "#PageHeaderPrimaryNav a img": function(evt) {
        var element = Event.findElement(evt);
        if(element && !element.id.match(/.*_active?/)) {
            element.src = "/images/" + element.id + ".gif";
        }
    }
}

/**
 * This is a map of resources used by the application.
 */
var resources = {
    nav: {
        images: {
            hover: {
                properties:     "/images/nav_properties_over.gif",
                financing:      "/images/nav_financing_over.gif",
                bulkPurchase:   "/images/nav_bulk_purchase_over.gif",
                about:          "/images/nav_about_over.gif",
                contact:        "/images/nav_contact_over.gif"
            }
        }
    },
    
    /**
     * This function loads the application resources
     */
    load: function() {
        var navHoverImages  = this.nav.images.hover;
        var src             = null;
        
        for(var img in navHoverImages) {
            src = navHoverImages[img];
            navHoverImages[img] = new Image();
            navHoverImages[img].src = src;
        }
    }
}

togglebox = {
    
    __disableFormElements: function(root, disable) {
        root.select("input:not([type=hidden])", "select", "textarea").each(function(e) {
            e.disabled = disable;
        });
    },
    
    setIsShowing: function(idOrElement, isShowing) {
        var element = $(idOrElement);
        if(element) {
            var titleShow   = element.down(".toggleboxTitleShow"),
                titleHide   = element.down(".toggleboxTitleHide"),
                content     = element.down(".toggleboxContent");
                
            if(isShowing) {
                titleShow.hide();
                titleHide.show();
                
                // Re-enable the form elements
                this.__disableFormElements(content, false);
                Effect.BlindDown(content, {duration: 0.2});
            } else {
                titleShow.show();
                titleHide.hide();
                
                // disable the form element, so they're not sent to the server.
                this.__disableFormElements(content, true);
                Effect.BlindUp(content, {duration: 0.2});
            }
        }
    }
}

/*-----------------------------------------------------------------------------
 *  WithLabel
 *---------------------------------------------------------------------------*/
var WithLabel = {
    LABEL_ATTR:   "wl:labeltext",
    forms:  []
}

// Initializes any with-label fields.  If an optional root element is
// supplied, the scope of the function application is limited to that element.
WithLabel.init = function(rootElement) {
    rootElement = $(rootElement || document.body);
    
    rootElement.select("["+ this.LABEL_ATTR + "]").each(function(e) {
        WithLabel.setDefaultIfEmpty(e);
        e.observe("focus", WithLabel.onFocus);
        e.observe("blur", WithLabel.onBlur);
        WithLabel.registerForm(e);
    });
}

// The onfocus callback for with-label fields.
WithLabel.onFocus = function(evt) {
    var e = evt.findElement();
    WithLabel.setEmptyIfDefault(e);
}

// The onblur callback for with-label fields.
WithLabel.onBlur = function(evt) {
    var e = evt.findElement();
    WithLabel.setDefaultIfEmpty(e);
}

// When called on an element, the element's value is cleared if its labeltext
// match its value.
WithLabel.setEmptyIfDefault = function(e) {
    if(e.value.strip() === e.getAttribute(WithLabel.LABEL_ATTR)) {
        e.value = "";
    }
}

// When called on an element, the element's value is set to its labeltext if 
// its value is empty.
WithLabel.setDefaultIfEmpty = function(e) {
    if(e.value.strip() === "") {
        e.value = e.getAttribute(WithLabel.LABEL_ATTR);
    }
}

WithLabel.registerForm = function(e) {
    var form = e.form;
    if(form) {
        if(!WithLabel.forms.member(form)) {
            WithLabel.forms.push(form);
            form.$elementsToClear = [];
            form.observe("submit", function(evt) {
                form.$elementsToClear.each(function(etc) {
                    WithLabel.setEmptyIfDefault(etc);
                });
            });
        }
        form.$elementsToClear.push(e);
    }
}

// This function establishes connections between window events and delegation rules.
Event.observe(window, "load", function() {
    resources.load();
    initializeFocus();
    
    var page = $("Page");
	page.delegate("change",     delegationRules.change);
	page.delegate("click",      delegationRules.click);
	page.delegate("mouseover",  delegationRules.over);
	page.delegate("mouseout",   delegationRules.out);
	
	WithLabel.init();
	
	// This fixes IE6s issue with bubbling onchange events.  This is a conditional
	// Comment, DO NOT REMOVE.
	/*@cc_on
	    $("state_prov")      && Event.observe($("state_prov"),      "change", delegationRules.submitForm)
	    $("min_price")       && Event.observe($("min_price"),       "change", delegationRules.submitForm)
	    $("max_price")       && Event.observe($("max_price"),       "change", delegationRules.submitForm)
	    $("min_beds")        && Event.observe($("min_beds"),        "change", delegationRules.submitForm)
	    $("max_beds")        && Event.observe($("max_beds"),        "change", delegationRules.submitForm)
	    $("min_baths")       && Event.observe($("min_baths"),       "change", delegationRules.submitForm)
	    $("max_baths")       && Event.observe($("max_baths"),       "change", delegationRules.submitForm)
	    $("property_type")   && Event.observe($("property_type"),   "change", delegationRules.submitForm)
	    $("sort_by")         && Event.observe($("sort_by"),         "change", delegationRules.submitForm)
	@*/
});
