/**
* Copyright (c) 2005 - 2008, James Auldridge
* All rights reserved.
*
* Licensed under the BSD, MIT, and GPL (your choice!) Licenses:
*  http://code.google.com/p/cookies/wiki/License
*
* Version 2.0
*/
var jaaulde = window.jaaulde || {};
jaaulde.utils = jaaulde.utils || {};
jaaulde.utils.cookies = (function() {
    var cookies = [];

    var defaultOptions = {
        hoursToLive: 0,
        path: '/',
        domain: window.location.hostname,
        secure: false
    };
    /**
    * resolveOptions - receive an options object and ensure all options are present and valid, replacing with defaults where necessary
    *
    * @access private
    * @static
    * @parameter Object options - optional options to start with
    * @return Object complete and valid options object
    */
    var resolveOptions = function(options) {
        var returnValue;

        if (typeof options !== 'object' || options === null) {
            returnValue = defaultOptions;
        }
        else {
            returnValue = {
                hoursToLive: (typeof options.hoursToLive === 'number' ? options.hoursToLive : defaultOptions.hoursToLive),
                path: (typeof options.path === 'string' && options.path != '' ? options.path : defaultOptions.path),
                domain: (typeof options.domain === 'string' && options.domain != '' ? options.domain : defaultOptions.domain),
                secure: (typeof options.secure === 'boolean' && options.secure != '' ? options.secure : defaultOptions.secure)
            };
        }

        return returnValue;
    };
    /**
    * assembleOptionsString - analyze options and assemble appropriate string for setting a cookie with those options
    *
    * @access private
    * @static
    * @parameter Object options - optional options to start with
    * @return String - complete and valid cookie setting options
    */
    var assembleOptionsString = function(options) {
        options = resolveOptions(options);

        return (
			(options.hoursToLive !== 0 ? '; expires=' + expiresGMTString(options.hoursToLive) : '') +
			'; path=' + options.path +
			'; domain=' + options.domain +
			(options.secure ? '; secure' : '')
		);
    };
    /**
    * expiresGMTString - add given number of hours to current date/time and convert to GMT string
    *
    * @access private
    * @static
    * @parameter Integer hoursToLive - number of hours for which cookie should be valid
    * @return String - GMT time representing current date/time plus number of hours given
    */
    var expiresGMTString = function(hoursToLive) {
        var dateObject = new Date();
        dateObject.setTime(dateObject.getTime() + (hoursToLive * 60 * 60 * 1000));

        return dateObject.toGMTString();
    };
    /**
    * splitCookies - retrieve document.cookie string and break it into a hash
    *
    * @access private
    * @static
    * @return Object - hash of cookies from document.cookie
    */
    var splitCookies = function() {
        cookies = [];
        var pair, name, separated = document.cookie.split(';');
        for (var i = 0; i < separated.length; i++) {
            pair = separated[i].split('=');
            name = pair[0].replace(/^\s*/, '').replace(/\s*$/, '');
            value = unescape(pair[1]);
            cookies[name] = unescape(value);
        }
        return cookies;
    };

    var constructor = function() { };

    /**
    * get - get one, several, or all cookies
    *
    * @access public
    * @paramater Mixed cookieName - String:name of single cookie; Array:list of multiple cookie names; Void (no param):if you want all cookies
    * @return Mixed - String:if single cookie requested and found; Null:if single cookie requested and not found; Object:hash of multiple or all cookies
    */
    constructor.prototype.get = function(cookieName) {
        var returnValue;

        splitCookies();

        if (typeof cookieName === 'string') {
            returnValue = (typeof cookies[cookieName] !== 'undefined') ? cookies[cookieName] : null;
        }
        else if (typeof cookieName === 'object' && cookieName !== null) {
            returnValue = [];
            for (var item in cookieName) {
                returnValue[cookieName[item]] = (typeof cookies[cookieName[item]] !== 'undefined') ? cookies[cookieName[item]] : null;
            }
        }
        else {
            returnValue = cookies;
        }

        return returnValue;
    };
    /**
    * set - set or delete a cookie with desired options
    *
    * @access public
    * @paramater String cookieName - name of cookie to set
    * @paramater Mixed value - Null:if deleting, String:value to assign cookie if setting
    * @paramater Object options - optional list of cookie options to specify
    * @return void
    */
    constructor.prototype.set = function(cookieName, value, options) //hoursToLive, path, domain, secure
    {
        if (typeof value === 'undefined' || value === null) {
            if (typeof options !== 'object' || options === null) {
                options = {};
            }
            value = '';
            options.hoursToLive = -8760;
        }

        var optionsString = assembleOptionsString(options);

        document.cookie = cookieName + '=' + escape(value) + optionsString;
    };
    /**
    * del - delete a cookie (domain and path options must match those with which the cookie was set; this is really an alias for set() with parameters simplified for this use)
    *
    * @access public
    * @paramater String cookieName - name of cookie to delete
    * @paramater Object options - optional list of cookie options to specify
    * @return void
    */
    constructor.prototype.del = function(cookieName, options) //path, domain
    {
        if (typeof options !== 'object' || options === null) {
            options = {};
        }
        this.set(cookieName, null, options);
    };
    /**
    * test - test whether the browser is accepting cookies
    *
    * @access public
    * @return Boolean
    */
    constructor.prototype.test = function() {
        var returnValue = false, testName = 'cT', testValue = 'data';

        this.set(testName, testValue);

        if (this.get(testName) == testValue) {
            this.del(testName);
            returnValue = true;
        }

        return returnValue;
    };
    /**
    * setOptions - set default options for calls to cookie methods
    *
    * @access public
    * @param Object options - list of cookie options to specify
    * @return void
    */
    constructor.prototype.setOptions = function(options) {
        if (typeof options !== 'object') {
            options = null;
        }

        defaultOptions = resolveOptions(options);
    }

    return new constructor();
})();


(function() {
    if (typeof jQuery !== 'undefined') {
        jQuery.cookies = jaaulde.utils.cookies;

        var extensions = {
            /**
            * $('selector').cookify - set the value of an input field to a cookie by the name or id of the field (radio and checkbox not supported)
            *
            * @access public
            * @param Object options - list of cookie options to specify
            * @return Object jQuery
            */
            cookify: function(options) {
                return this.each(function() {
                    var name = '', value = '', nameAttrs = ['name', 'id'], iteration = 0, inputType;

                    while (iteration < nameAttrs.length && (typeof name !== 'string' || name === '')) {
                        name = jQuery(this).attr(nameAttrs[iteration]);
                        iteration++;
                    }

                    if (typeof name === 'string' || name !== '') {
                        inputType = jQuery(this).attr('type').toLowerCase();
                        if (inputType !== 'radio' && inputType !== 'checkbox') {
                            value = jQuery(this).attr('value');
                            if (typeof value !== 'string' || value === '') {
                                value = null;
                            }
                            jQuery.cookies.set(name, value, options);
                        }
                    }

                    iteration = 0;
                });
            },
            /**
            * $('selector').cookieFill - set the value of an input field or the innerHTML of an element from a cookie by the name or id of the field or element
            *
            * @access public
            * @return Object jQuery
            */
            cookieFill: function() {
                return this.each(function() {
                    var name = '', value, nameAttrs = ['name', 'id'], iteration = 0, nodeType;

                    while (iteration < nameAttrs.length && (typeof name !== 'string' || name === '')) {
                        name = jQuery(this).attr(nameAttrs[iteration]);
                        iteration++;
                    }

                    if (typeof name === 'string' && name !== '') {
                        value = jQuery.cookies.get(name);
                        if (value !== null) {
                            nodeType = this.nodeName.toLowerCase();
                            if (nodeType === 'input' || nodeType === 'textarea') {
                                jQuery(this).attr('value', value);
                            }
                            else {
                                jQuery(this).html(value);
                            }
                        }
                    }

                    iteration = 0;
                });
            },
            /**
            * $('selector').cookieBind - call cookie fill on matching elements, and bind their change events to cookify()
            *
            * @access public
            * @param Object options - list of cookie options to specify
            * @return Object jQuery
            */
            cookieBind: function(options) {
                return this.each(function() {
                    $(this).cookieFill().change(function() {
                        $(this).cookify(options);
                    });
                });
            }
        };

        jQuery.each(extensions, function(i) {
            jQuery.fn[i] = this;
        });
    }
})();