/**
 * @license AngularJS v1.0.7
 * (c) 2010-2012 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function (window, angular, undefined) {
    'use strict';

    /**
     * @ngdoc overview
     * @name ngCookies
     */


    angular.module('ngCookies', ['ng']).
    /**
     * @ngdoc object
     * @name ngCookies.$cookies
     * @requires $browser
     *
     * @description
     * Provides read/write access to browser's cookies.
     *
     * Only a simple Object is exposed and by adding or removing properties to/from
     * this object, new cookies are created/deleted at the end of current $eval.
     *
     * @example
     <doc:example>
     <doc:source>
     <script>
     function ExampleController($cookies) {
           // Retrieving a cookie
           var favoriteCookie = $cookies.myFavorite;
           // Setting a cookie
           $cookies.myFavorite = 'oatmeal';
         }
     </script>
     </doc:source>
     </doc:example>
     */
        factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
            var cookies = {},
                lastCookies = {},
                lastBrowserCookies,
                runEval = false,
                copy = angular.copy,
                isUndefined = angular.isUndefined;

            //creates a poller fn that copies all cookies from the $browser to service & inits the service
            $browser.addPollFn(function () {
                var currentCookies = $browser.cookies();
                if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
                    lastBrowserCookies = currentCookies;
                    copy(currentCookies, lastCookies);
                    copy(currentCookies, cookies);
                    if (runEval) $rootScope.$apply();
                }
            })();

            runEval = true;

            //at the end of each eval, push cookies
            //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
            //      strings or browser refuses to store some cookies, we update the model in the push fn.
            $rootScope.$watch(push);

            return cookies;


            /**
             * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.
             */
            function push() {
                var name,
                    value,
                    browserCookies,
                    updated;

                //delete any cookies deleted in $cookies
                for (name in lastCookies) {
                    if (isUndefined(cookies[name])) {
                        $browser.cookies(name, undefined);
                    }
                }

                //update all cookies updated in $cookies
                for (name in cookies) {
                    value = cookies[name];
                    if (!angular.isString(value)) {
                        if (angular.isDefined(lastCookies[name])) {
                            cookies[name] = lastCookies[name];
                        } else {
                            delete cookies[name];
                        }
                    } else if (value !== lastCookies[name]) {
                        $browser.cookies(name, value);
                        updated = true;
                    }
                }

                //verify what was actually stored
                if (updated) {
                    updated = false;
                    browserCookies = $browser.cookies();

                    for (name in cookies) {
                        if (cookies[name] !== browserCookies[name]) {
                            //delete or reset all cookies that the browser dropped from $cookies
                            if (isUndefined(browserCookies[name])) {
                                delete cookies[name];
                            } else {
                                cookies[name] = browserCookies[name];
                            }
                            updated = true;
                        }
                    }
                }
            }
        }]).


    /**
     * @ngdoc object
     * @name ngCookies.$cookieStore
     * @requires $cookies
     *
     * @description
     * Provides a key-value (string-object) storage, that is backed by session cookies.
     * Objects put or retrieved from this storage are automatically serialized or
     * deserialized by angular's toJson/fromJson.
     * @example
     */
        factory('$cookieStore', ['$cookies', function ($cookies) {

            return {
                /**
                 * @ngdoc method
                 * @name ngCookies.$cookieStore#get
                 * @methodOf ngCookies.$cookieStore
                 *
                 * @description
                 * Returns the value of given cookie key
                 *
                 * @param {string} key Id to use for lookup.
                 * @returns {Object} Deserialized cookie value.
                 */
                get: function (key) {
                    var value = $cookies[key];
                    return value ? angular.fromJson(value) : value;
                },

                /**
                 * @ngdoc method
                 * @name ngCookies.$cookieStore#put
                 * @methodOf ngCookies.$cookieStore
                 *
                 * @description
                 * Sets a value for given cookie key
                 *
                 * @param {string} key Id for the `value`.
                 * @param {Object} value Value to be stored.
                 */
                put: function (key, value) {
                    $cookies[key] = angular.toJson(value);
                },

                /**
                 * @ngdoc method
                 * @name ngCookies.$cookieStore#remove
                 * @methodOf ngCookies.$cookieStore
                 *
                 * @description
                 * Remove given cookie
                 *
                 * @param {string} key Id of the key-value pair to delete.
                 */
                remove: function (key) {
                    delete $cookies[key];
                }
            };

        }]);


})(window, window.angular);
