// the goal: provide menu which will remember it's state in cookie variable

// define dummy replacements for firebug functionality (needed for Opera)
if (window.opera && !window.console) {
    window.console = {};
    function fn() {
        opera.postError(arguments);
    };
    ['log', 'debug', 'info', 'warn', 'error', 'assert', 'dir', 'dirxml', 'group', 'groupEnd', 
    'time', 'timeEnd', 'count', 'trace', 'profile', 'profileEnd'].forEach(function(name) {
        window.console[name] = fn;
    });
}            
(function() {
        var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
        if(!window.console){
            window.console = {};
        }
        for (var i in names) {
            window.console[names[i]] = window.console[names[i]] || function(){
                return;
            };
        }
})();

(function($) {
    
    var C = function(userConfig) {
        var defaultConfig = {
            key: 'cm', // cookie key
            items: []
        };
    
        var defaultState = {
            selectedNav: null,
            selected: null 
        };
    
        var config;  // initial configuration hash, list of items, behavior and styles
        var state = $.extend({}, defaultState);   // all state information, this has to be persistent across page refreshes

        /////////////////////////////////////////////////////////////////////////////////////////////////////////
        // helpers

        // parseUri 1.2.2
        // (c) Steven Levithan <stevenlevithan.com>
        // MIT License
        function parseUri(str) {
            var o   = parseUri.options,
                m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
                uri = {},
                i   = 14;

            while (i--) uri[o.key[i]] = m[i] || "";

            uri[o.q.name] = {};
            uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
                if ($1) uri[o.q.name][$1] = $2;
            });

            return uri;
        };

        parseUri.options = {
            strictMode: false,
            key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
            q:   {
                name:   "queryKey",
                parser: /(?:^|&)([^&=]*)=?([^&]*)/g
            },
            parser: {
                strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
                loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
            }
        };
    
        function refreshPage() {
            var opts = parseUri(document.location+"");
            var url = opts['protocol']+'://'+opts['host']+opts['path'];
            document.location = url; // reload without parameters
        }
    
        function storeState() {
            var sid = config.key;
            console.log('store state ', sid);
            $.cookie(sid, JSONXXXTR.stringify(state));
        }

        function restoreState() {
            var sid = config.key;
            console.log('restore state ', sid);
            var s = $.cookie(sid);
            if (s) { 
                try {
                    s = JSONXXXTR.parse(s);
                } catch (e) {
                    console.error('unable to restore state:', s);
                    return;
                }
                state = $.extend({}, defaultState, s);
                console.log('  state:', state);
            }
        }
    
        function sanitizeState() {
            if (!config.nav) {
                for (var i=0; i < config.items.length; i++) {
                    var item = config.items[i];
                    if (item.id==state.selected) return;
                }
                state.selected = config.items[0].id; // select first item if none selected
            } else {
                for (i=0; i < config.nav.length; i++) {
                    var nav = config.nav[i];
                    if (nav.id==state.selectedNav) {
                        for (var j=0; j < nav.items.length; j++) {
                            item = nav.items[j];
                            if (item==state.selected) return;
                        }
                        state.selected = nav.items[0]; // select first item if none selected
                        return;
                    }
                }
                state.selectedNav = config.nav[0].id; // select first item if none selected
                state.selected = config.nav[0].items[0]; // select first item if none selected
            }
        }
        
        
        function renderNav(items) {
            var container = $('<div class="tr-cookiemenu-nav">');
            for (var i=0; i < items.length; i++) {
                var item = items[i];
                var el = $('<div class="tr-cookiemenu-nav-item"/>');
                if (item.id==state.selectedNav) {
                    el.html(item.title);
                } else {
                    var a = $('<a/>').html(item.title);
                    (function(item) {
                        a.bind('click', function() {
                            console.log('clicked ', item.id);
                            state.selectedNav = item.id;
                            sanitizeState();
                            storeState();
                            refreshPage();
                        });
                    })(item);
                    el.append(a);
                }
                if (i) container.append('<div class="tr-cookiemenu-nav-sep">|</div>');
                container.append(el);
            }
            config.root.append(container);
            config.root.append($('<div class="tr-cookiemenu-nav-clear"/>'));
        }
        
        function renderItems(items) {
            var container = $('<div class="tr-cookiemenu">');
            for (var i=0; i < items.length; i++) {
                var item = items[i];
                var el = $('<div class="tr-cookiemenu-item"/>');
                if (item.id==state.selected) {
                    el.html(item.title);
                } else {
                    var a = $('<a/>').html(item.title);
                    (function(item) {
                        a.bind('click', function() {
                            console.log('clicked ', item.id);
                            state.selected = item.id;
                            storeState();
                            refreshPage();
                        });
                    })(item);
                    el.append(a);
                }
                if (i) container.append('<div class="tr-cookiemenu-sep">|</div>');
                container.append(el);
            }
            if (config.hideSecondary) container.hide();
            config.root.append(container);
            config.root.append($('<div class="tr-cookiemenu-clear"/>'));
        }
        
        /////////////////////////////////////////////////////////////////////////////////////////////////////////
        // UI updating
        //
        // this function is capable of doing heavy duty UI update according to passed state object
        function updateUI() {
            sanitizeState();
            console.log('CM-UI', state, config);
            config.root.empty();
            if (!config.nav) {
                renderItems(config.items);
            } else {
                renderNav(config.nav);
                for (var i=0; i < config.nav.length; i++) {
                    var nav = config.nav[i];
                    if (nav.id==state.selectedNav) {
                        var x = [];
                        for (var j=0; j < nav.items.length; j++) {
                            var ii = nav.items[j];
                            for (var z=0; z< config.items.length; z++) {
                                if (config.items[z].id==ii) {
                                    x.push(config.items[z]); 
                                }
                            }
                        }
                        renderItems(x);
                    }
                }
            }
        };

        config = $.extend({}, defaultConfig, userConfig);
    
        // restore state from cookies
        restoreState();

        // override active item if passed from URL
        var opts = parseUri(document.location+"");
        if (opts.queryKey['cm']) {
            state.selected = opts.queryKey['cm'];
        }
        if (opts.queryKey['mm']) {
            state.selectedNav = opts.queryKey['mm'];
        }
        updateUI();
        storeState();
    };
    
    if (!window["Transpond"]) window.Transpond = {};
    window.Transpond.renderCookieMenu = function(element, userConfig) { // main entry point
        var config = $.extend({}, userConfig);
        config.root = $(element);
        return new C(config);
    };
    
    $.fn.TrCookieMenu = function(options) {
        return this.each(function() {
            Transpond.renderCookieMenu(this, options);
        });
    };
    
})(jQuery);
