/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/

/**
* Create a cookie with the given name and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
*       used when the cookie was set.
*
* @param String name The name of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
*                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
*                             If set to null or omitted, the cookie will be a session cookie and will not be retained
*                             when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
*                        require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/

/**
* Get the value of a cookie with the given name.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String name The name of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/

jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};


/**
* Copyright (c) 2005 - 2010, James Auldridge
* All rights reserved.
*
* Licensed under the BSD, MIT, and GPL (your choice!) Licenses:
*  http://code.google.com/p/cookies/wiki/License
*
*/
var jaaulde = window.jaaulde || {};
jaaulde.utils = jaaulde.utils || {};
jaaulde.utils.cookies = (function() {
    var resolveOptions, assembleOptionsString, parseCookies, constructor, defaultOptions = {
        expiresAt: null,
        path: '/',
        domain: null,
        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
    */
    resolveOptions = function(options) {
        var returnValue, expireDate;

        if (typeof options !== 'object' || options === null) {
            returnValue = defaultOptions;
        }
        else {
            returnValue = {
                expiresAt: defaultOptions.expiresAt,
                path: defaultOptions.path,
                domain: defaultOptions.domain,
                secure: defaultOptions.secure
            };

            if (typeof options.expiresAt === 'object' && options.expiresAt instanceof Date) {
                returnValue.expiresAt = options.expiresAt;
            }
            else if (typeof options.hoursToLive === 'number' && options.hoursToLive !== 0) {
                expireDate = new Date();
                expireDate.setTime(expireDate.getTime() + (options.hoursToLive * 60 * 60 * 1000));
                returnValue.expiresAt = expireDate;
            }

            if (typeof options.path === 'string' && options.path !== '') {
                returnValue.path = options.path;
            }

            if (typeof options.domain === 'string' && options.domain !== '') {
                returnValue.domain = options.domain;
            }

            if (options.secure === true) {
                returnValue.secure = options.secure;
            }
        }

        return returnValue;
    };
    /**
    * assembleOptionsString - analyze options and assemble appropriate string for setting a cookie with those options
    *
    * @access private
    * @static
    * @parameter options OBJECT - optional options to start with
    * @return STRING - complete and valid cookie setting options
    */
    assembleOptionsString = function(options) {
        options = resolveOptions(options);

        return (
			(typeof options.expiresAt === 'object' && options.expiresAt instanceof Date ? '; expires=' + options.expiresAt.toGMTString() : '') +
			'; path=' + options.path +
			(typeof options.domain === 'string' ? '; domain=' + options.domain : '') +
			(options.secure === true ? '; secure' : '')
		);
    };
    /**
    * parseCookies - retrieve document.cookie string and break it into a hash with values decoded and unserialized
    *
    * @access private
    * @static
    * @return OBJECT - hash of cookies from document.cookie
    */
    parseCookies = function() {
        var cookies = {}, i, pair, name, value, separated = document.cookie.split(';'), unparsedValue;
        for (i = 0; i < separated.length; i = i + 1) {
            pair = separated[i].split('=');
            name = pair[0].replace(/^\s*/, '').replace(/\s*$/, '');

            try {
                value = decodeURIComponent(pair[1]);
            }
            catch (e1) {
                value = pair[1];
            }

            if (typeof JSON === 'object' && JSON !== null && typeof JSON.parse === 'function') {
                try {
                    unparsedValue = value;
                    value = JSON.parse(value);
                }
                catch (e2) {
                    value = unparsedValue;
                }
            }

            cookies[name] = value;
        }
        return cookies;
    };

    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 - Value of cookie as set; Null:if only one cookie is requested and is not found; Object:hash of multiple or all cookies (if multiple or all requested);
    */
    constructor.prototype.get = function(cookieName) {
        var returnValue, item, cookies = parseCookies();

        if (typeof cookieName === 'string') {
            returnValue = (typeof cookies[cookieName] !== 'undefined') ? cookies[cookieName] : null;
        }
        else if (typeof cookieName === 'object' && cookieName !== null) {
            returnValue = {};
            for (item in cookieName) {
                if (typeof cookies[cookieName[item]] !== 'undefined') {
                    returnValue[cookieName[item]] = cookies[cookieName[item]];
                }
                else {
                    returnValue[cookieName[item]] = null;
                }
            }
        }
        else {
            returnValue = cookies;
        }

        return returnValue;
    };
    /**
    * filter - get array of cookies whose names match the provided RegExp
    *
    * @access public
    * @paramater Object RegExp - The regular expression to match against cookie names
    * @return Mixed - Object:hash of cookies whose names match the RegExp
    */
    constructor.prototype.filter = function(cookieNameRegExp) {
        var cookieName, returnValue = {}, cookies = parseCookies();

        if (typeof cookieNameRegExp === 'string') {
            cookieNameRegExp = new RegExp(cookieNameRegExp);
        }

        for (cookieName in cookies) {
            if (cookieName.match(cookieNameRegExp)) {
                returnValue[cookieName] = cookies[cookieName];
            }
        }

        return returnValue;
    };
    /**
    * set - set or delete a cookie with desired options
    *
    * @access public
    * @paramater String cookieName - name of cookie to set
    * @paramater Mixed value - Any JS value. If not a string, will be JSON encoded; NULL to delete
    * @paramater Object options - optional list of cookie options to specify
    * @return void
    */
    constructor.prototype.set = function(cookieName, value, options) {
        if (typeof options !== 'object' || options === null) {
            options = {};
        }

        if (typeof value === 'undefined' || value === null) {
            value = '';
            options.hoursToLive = -8760;
        }

        else if (typeof value !== 'string') {
            if (typeof JSON === 'object' && JSON !== null && typeof JSON.stringify === 'function') {
                value = JSON.stringify(value);
            }
            else {
                throw new Error('cookies.set() received non-string value and could not serialize.');
            }
        }


        var optionsString = assembleOptionsString(options);

        document.cookie = cookieName + '=' + encodeURIComponent(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 MIxed cookieName - String name of cookie to delete, or Bool true to delete all
    * @paramater Object options - optional list of cookie options to specify ( path, domain )
    * @return void
    */
    constructor.prototype.del = function(cookieName, options) {
        var allCookies = {}, name;

        if (typeof options !== 'object' || options === null) {
            options = {};
        }

        if (typeof cookieName === 'boolean' && cookieName === true) {
            allCookies = this.get();
        }
        else if (typeof cookieName === 'string') {
            allCookies[cookieName] = true;
        }

        for (name in allCookies) {
            if (typeof name === 'string' && name !== '') {
                this.set(name, 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 (window.jQuery) {
        (function($) {
            $.cookies = jaaulde.utils.cookies;

            var extensions = {
                /**
                * $( 'selector' ).cookify - set the value of an input field, or the innerHTML of an element, to a cookie by the name or id of the field or element
                *                           (field or element MUST have name or id attribute)
                *
                * @access public
                * @param options OBJECT - list of cookie options to specify
                * @return jQuery
                */
                cookify: function(options) {
                    return this.each(function() {
                        var i, nameAttrs = ['name', 'id'], name, $this = $(this), value;

                        for (i in nameAttrs) {
                            if (!isNaN(i)) {
                                name = $this.attr(nameAttrs[i]);
                                if (typeof name === 'string' && name !== '') {
                                    if ($this.is(':checkbox, :radio')) {
                                        if ($this.attr('checked')) {
                                            value = $this.val();
                                        }
                                    }
                                    else if ($this.is(':input')) {
                                        value = $this.val();
                                    }
                                    else {
                                        value = $this.html();
                                    }

                                    if (typeof value !== 'string' || value === '') {
                                        value = null;
                                    }

                                    $.cookies.set(name, value, options);

                                    break;
                                }
                            }
                        }
                    });
                },
                /**
                * $( '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 jQuery
                */
                cookieFill: function() {
                    return this.each(function() {
                        var n, getN, nameAttrs = ['name', 'id'], name, $this = $(this), value;

                        getN = function() {
                            n = nameAttrs.pop();
                            return !!n;
                        };

                        while (getN()) {
                            name = $this.attr(n);
                            if (typeof name === 'string' && name !== '') {
                                value = $.cookies.get(name);
                                if (value !== null) {
                                    if ($this.is(':checkbox, :radio')) {
                                        if ($this.val() === value) {
                                            $this.attr('checked', 'checked');
                                        }
                                        else {
                                            $this.removeAttr('checked');
                                        }
                                    }
                                    else if ($this.is(':input')) {
                                        $this.val(value);
                                    }
                                    else {
                                        $this.html(value);
                                    }
                                }

                                break;
                            }
                        }
                    });
                },
                /**
                * $( 'selector' ).cookieBind - call cookie fill on matching elements, and bind their change events to cookify()
                *
                * @access public
                * @param options OBJECT - list of cookie options to specify
                * @return jQuery
                */
                cookieBind: function(options) {
                    return this.each(function() {
                        var $this = $(this);
                        $this.cookieFill().change(function() {
                            $this.cookify(options);
                        });
                    });
                }
            };

            $.each(extensions, function(i) {
                $.fn[i] = this;
            });

        })(window.jQuery);
    }
})();
