/*
    Namespace framework object for entire site. 
*/



Event.observe
(
    window, 
    "unload", 
    function()
    {
        if (page)
            if (page.destroy)
                page.destroy();
        
        page = null;
        
    }
);

Prototype.Browser.IE6 = Prototype.Browser.IE && navigator.appVersion.match("IE 6") != null;


var Site = {

    NAME: "Site Name",

    Pages: 
    {
        // an object container for individual pages in the site
    },

    Widgets:
    {
        
    },
    
    Controllers:
    {

    },
    
    
    TEMPLATES:
    {
        // CHANGED: 08 Feb 2008
        SALE_TOOLTIP:
			          '<div id="sale-tooltip-#{saleNumber}" class="tooltip" style="display: none;">'
                    + '<div class="cap-tp"><div>&nbsp;</div></div><div class="clearer"></div><div class="body">'
                    + '<h6>Auction Times</h6>' 
			        + '<table class="times">'
				    + '#{auctionTimes}'
				    + '</table>'
				    + '<h6>Viewing Times</h6>'
				    + '<table class="times">'
				    + '#{viewingTimes}'
				    + '</table>'
				    + '</div><div class="clearer"></div><div class="cap-bt"></div>'
                    + '</div>' + "\n",
            
        SALE_TOOLTIP_AUCTION_TIME:
              '<tr><td>#{time}</td></tr>',

        SALE_TOOLTIP_VIEWING_TIME:
                '<tr>'
			  + '<th scope="row">#{date}</th>'
			  + '<td>#{timeLow} - #{timeHigh}</td>'
			  + '</tr>'
    },
    
    DURATION_CATEGORIES_MENU: 0.0,
    
    /* 
        Here we give WebKit (Safari) fade durations as it is currently the only rendering engine that does Scriptaculous fades gracefully
        All the other browses show weird text artifacts during the animation 
     */
    
    DEFAULT_SHOW_DURATION: Prototype.Browser.WebKit ? 0.2 : 0,  
    DEFAULT_HIDE_DURATION: Prototype.Browser.WebKit ? 0.1 : 0,
    
    formatNumber: function(number, format)
    {
        var formatted;
    	var formattedDec = '';
    	var formattedWhole = '';

    	var strWhole;

    	var value = Math.abs(number);
    	var valueWhole = Math.floor(value);

    	var formatter = format;

    	var parenthesis = false;

    	// check if negative values should use parenthesis formatting

    	var matches = formatter.match(/\((.*?)\)/, "ig");

    	if (matches && matches.length > 0)
    	{
    		parenthesis = true;

    		// take the rest of the string as the actual formatter
    		formatter = matches[1];
    	}

    	var formatterWhole = formatter;

    	var parts = formatter.split(".");

    	if (parts.length > 1)
    	{
    		// the string has a decimal part
    		value = value.toFixed(parts[1].length);	

    		formatterWhole = parts[0];
    	}
    	else
    	{
    		valueWhole = Math.round(value);	
    	}

    	// now work out how to format the whole number part
    	formatted = value.toString();

    	if (parts.length > 1)
    	{
    		formattedDec = "." + formatted.split(".")[1];
    	}

    	strWhole = Math.abs(valueWhole).toString();

    	// first, pad out formatterWhole up to the length of valueWhole, with #  

    	var count = 0;

    	formatterWhole.toArray().each
    	(
    		function (chr)
    		{
    			if (chr == '#' || chr == '0')
    				count++;
    		}
    	);

    	matches = formatterWhole.match(/[^#0,]*?([#0,]+)[^#0,]*?/);

    	if (matches.length > 1)
    	{
    		formatterWhole = formatterWhole.replace(matches[1], "#".times(strWhole.length - count) + matches[1]);
    	}

    	var formatterChars = formatterWhole.toArray();

    	var digitIndex = strWhole.length - 1;

    	for (var i = formatterChars.length - 1; i>=0; i--)
    	{
    		// process each character in the formatter string 

    		var chr = formatterChars[i];
    		var ten = Math.pow(10, strWhole.length - 1 - digitIndex);


    		if (chr == '#')
    		{
    			if (valueWhole >= ten)
    			{
    				formattedWhole = strWhole.substr(digitIndex, 1) + formattedWhole;
    			} 
    			// otherwise add nothing
    			digitIndex = digitIndex - 1;	
    		}
    		else if (chr == '0')
    		{
    			if (valueWhole >= ten)
    			{
    				formattedWhole = strWhole.substr(digitIndex, 1) + formattedWhole;
    			} 
    			else
    			{
    				// otherwise add a 0
    				formattedWhole = '0' + formattedWhole;
    			}
	
    			digitIndex = digitIndex - 1;
    		}
    		else if (chr == ',')
    		{
    			if (valueWhole >= ten)
    			{
    				formattedWhole = chr + formattedWhole;
    			}
    		}
    		else
    		{
    			formattedWhole = chr + formattedWhole;
    		}
    	}

    	// apply the parenthesis if the original value is negative

    	if (number < 0)
    	{
    		if (parenthesis)
    			return '(' + formattedWhole + formattedDec + ')';
    		else
    			return '-' + formattedWhole + formattedDec;
    	}

    	return (formattedWhole + formattedDec);
    },
    
    processWindowOptions: function(options)
    {
        var matches;
        var width;
        var height;
        
        var ret = options;
        
        // first, check if a width is available
        matches = options.match(/width=([\d]+)/);
        
        if (matches)
        {
            width = parseInt(matches[1]);
            
            // replace any references to "c" as left value with screen center
            ret = ret.replace(/left\=c/, 'left=' + ((screen.availWidth - width) / 2));     
        }
        
        // first, check if a width is available
        matches = options.match(/height=([\d]+)/);
        
        if (matches)
        {
            height = parseInt(matches[1]);
            
            // replace any references to "c" as top value with screen center
            ret = ret.replace(/top\=c/, 'top=' + ((screen.availHeight - height) / 2));        
        }
        
        return ret;
    } 
};


Number.prototype.leadingZero = function(toLength)
{
    return ("0").times( (toLength || 2) - this.toString().length ) + this.toString();
};
    
Date.prototype.fullYear = function() 
{
    var x = this.getYear();
    var y = x % 100;
    y += (y < 38) ? 2000 : 1900;
    return y;
};

Date.daysInMonth = function(month, year)
{
    switch (month)
	{
		case 8:
		case 3:
		case 5:
		case 10:
		{
			return 30;
			break;
		}
		case 1:
	    {
			return (Jel.Date.isLeapYear(year) ? 29 : 28);
			break;
		}
		default:
		{
			return 31;
		}
	}
};

Date.MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

/*
    Base object for all objects in the site.
    
    Contains useful functions to:
    
        * apply an options hash over a set of default options ( a very common pattern in JS class constructors )
        * add event observers to an observers hash (that is, functions bound using bindAsEventListener)
        * add block functions to an observers hash (that is, functions bound using bind)

*/  

Site.Base = Class.create
(
    {
        initialize: function()
        {
            this.addBlocks("release");
        },
        
        setOptions: function(options, defaultOptions)
        {
            this.options = Object.extend
            (
                defaultOptions || {},
                options || {}
            );
        },
        
        addObservers: function()
        {
            this.observers = this.observers || {};
            
            $A(arguments).each
            (
                function(arg)
                {
                    if (this[arg])
                        this.observers[arg] = this[arg].bindAsEventListener(this);
                },
                this
            );
        },
        
        release: function()
        {
            // sets an object to null and calls the "destroy" method on an object, if it exists
            // can be used in Enumerable.each, for arrays of objects
            
            for (i=0; i<arguments.length; i++)
            {
                if (arguments[i])
                    if (arguments[i].destroy)
                        arguments[i].destroy();
                
                arguments[i] = null;
            }
        },
        
        addBlocks: function()
        {
            this.blocks = this.blocks || {};
            
            $A(arguments).each
            (
                function(arg)
                {
                    if (this[arg])
                        this.blocks[arg] = this[arg].bind(this);
                },
                this
            );
        },
        
        destroy: function()
        {
            
        }
    }
);

/*
    An extension to Prototype's Template class, which allows templates to be applied 
    successively without clearing patterns that don't exist in the evaluated object (grrr, wish there was an option)
*/


Object.extend
(
    Template.prototype,
    {
        evaluatep: function(object)
        {
            if (Object.isFunction(object.toTemplateReplacements))
                    object = object.toTemplateReplacements();

            return this.template.gsub
            (
                this.pattern, 
                
                function(match) 
                {
                    if (object == null) 
                    {
                        return '';
                    }
                
                    var preserve = match[0];
                
                    var before = match[1] || '';
            
                    if (before == '\\') 
                        return match[2];

                    var ctx = object, expr = match[3];

                    var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
            
                    if (match == null) 
                        return before;

                    while (match != null) 
                    {
                        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
                        ctx = ctx[comp];
                    
                        if (null == ctx)
                            return preserve;
                    
                        if (null == ctx || '' == match[3]) 
                        {
                            break;
                        }
                        
                        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
                        match = pattern.exec(expr);
                    }

                    return before + String.interpret(ctx);
                },
                this
            );
        }
    }
);


Object.extend
(
    String.prototype,
    {
        interpolatep: function(object, pattern) 
        {
            return new Template(this, pattern).evaluatep(object);
        }
    }  
);


Element.addMethods
(
    {
        observeSelect: function(element, eventName, observer, selector)
        {
            $(element).select(selector).invoke("observe", eventName, observer);
        },
        
        matchUp: function(element, selector)
        {
            var ret = element;
            
            while (!ret.match(selector) && ret.parentNode)
            {
                ret = ret.up();
            }
            
            return ret;
        },
        
        matchDown: function(element, selector)
        {
            return element.match(selector) ? element : element.down(selector);
        },
        
        removeClassNameSelect: function(element, className, selector)
        {
            $(element).select(selector).invoke("removeClassName", className);
        },
        
        addClassNameSelect: function(element, className, selector)
        {
            $(element).select(selector).invoke("addClassName", className);
        }
    }
);
