/**
 * VPRO's Navigation widget embeds a widget containing links to related VPRO sites and pages.
 * It also creates the VPRO.nl logo button animation.
 *
 * @requires $vpro A VPRO version of jQuery (...url...)
 * @author VPRO widgets[at]vpro.nl
 *
 * Version 2.0.1-SNAPSHOT, used for the Thonik 2010 rebrand
 */

if (!window.vpro) {
     window.vpro = {};
}

if (!window.vpro.widget) {
     window.vpro.widget = {};
}

if (!window.vpro.widget.Navigation && !window.$vpro) {
(function(){
    var TEMPLATE_BAR = ''.concat(
        '<div id="vpro_nav" class="{vpro_navigation_class}"><div id="vpro_nav_wrap">',
        '<div id="vpro_nav_header"><a href="http://www.vpro.nl" id="vpro_nav_logo"><span>VPRO</span></a>',
        '<ul class="vpro_nav_blinds"><li><a name="nieuws" href="http://nieuws.vpro.nl">Nieuws</a></li><li><a name="gids" href="http://gids.vpro.nl">Gids</a></li><li><a name="gemist" href="http://afspelen.vpro.nl">Afspelen</a></li><li><a name="winkel" href="http://winkel.vpro.nl">Winkel</a></li><li><a name="leden" href="http://leden.vpro.nl">Leden</a></li><li><form id="vpro_nav_search" method="get" action="http://www.vpro.nl/zoeken/"><div><input class="query" type="text" name="q" value="Zoeken" /><input type="hidden" name="cx" value="005354543932881943412:t45z03utoiy" /><input type="hidden" name="cof" value="FORID:11" /><input type="hidden" name="ie" value="UTF-8" /><input type="hidden" name="pl" value="20" /><input type="hidden" name="scope" value="vpro" /></div><input type="submit" value="" class="submit" title="Zoeken" /></form></li></ul><a href="?" title="Sluiten" class="vpro_nav_close">x</a>',
        '</div><div class="vpro_nav_clear"></div>',
        '<dl id="vpro_nav_related"><dt>',
        '<strong class="vpro_related_label"><span class="vpro_related_categories">{related_categories}</span>:</strong><p>De VPRO heeft naast <span class="vpro_related_site">{related_site}</span> deze andere sites over het onderwerp <span class="vpro_related_categories">{related_categories}</span></p>',
        '</dt><dd><ol>{related_items}</ol></dd></dl><div class="vpro_nav_clear"></div>',
        '<ul id="vpro_nav_footer"><li><a name="lid-vpro" href="http://www.vpro.nl/formulieren/42461632/word+lid+van+de+vpro"><span>Word lid van de VPRO</span></a></li><li><a name="lid-gids" href="http://www.vpro.nl/formulieren/42562193/abonnement+op+vpro+gids"><span>Abonneer op VPRO Gids</span></a></li><li class="vpro_nav_second"><a name="programmas=sites" href="http://www.vpro.nl/a-z-index"><span>Programma\'s en Sites</span></a></li><li class="vpro_nav_first"><a name="sluiten" class="vpro_nav_close" href="?"><span>Sluiten X</span></a></li></ul>',
        '</div><div id="vpro_nav_footer_bar"></div></div>'
    );

    var MADE,
        TEMPLATE_RELATED_ITEM = ''.concat(
            '<li><div class="vpro_related_item"><a href="{related_item_url}">',
            '<img src="{related_item_image}+s(171)+part(0,5,171,81)+f(jpg)"',
            ' alt="" /><span>{related_item_title}</span></a>',
            '<p>{related_item_description}</p></div></li>'
        ),
        TEMPLATE_WRAPS = [],
        VERSION = "2",
        PATH = "http://files.vpro.nl/centrale-navigatie/v" + VERSION + "/";

    vpro.widget.Navigation = {
        ASSET_JQUERY : PATH + "jquery.vpro.1.3.2.pack.js",
        ASSET_CSS : PATH + "css/vpro_nav.css",
        ASSET_CSS_IE6 : PATH + "css/vpro_nav_ie6.css",
        RELATED_DATA_URL: "http://www.vpro.nl/vpronavigatie/centrale/?referrer={referrer}&teaser={site}",
        IMAGE_PATH : "http://images.vpro.nl/img.db?",
        BUTTON_1 : 42845287,
        BUTTON_2 : 42845291,
        BUTTON_3 : 42845298,
        ANIM_SPEED: 550,
        ANIM_EASE: "swing",
        MIN_WIDTH: 981,
        MAX_WIDTH: 981,
        CLASS_OVERFLOW : "vpro_nav_overflow",
        HIDDEN: 0,
        SHOWN: 1,

        getInstance : function(config) {
            if (typeof MADE != "undefined") {
                return MADE;
            } else {
                return new vpro.widget.Navigation.Bar(config);
            }
        },

        /**
            * The VPRO related sites/info navigation bar (Singleton).
            *
            * @param config Hash of options
            *        @option triggers Array of jQuery selector strings,
            *                which items should trigger the navigation
            *                @default #vpro_nav_button
            *        @option triggerApproach Number of pixels distance to trigger the 'nearby' button animation
                            @default 100
            *        @option templateClass String CSS class of the navigation,
            *                vpro_nav_red
            *                @default no class
            *        @option label Boolean if a VPRO label button should be generated that will trigger the navigation
            *        @option    site Number of a VPRO site teaser as used in http://www.vpro.nl/a-z-index
            *                if no site is provided, the current document location will be used to determine the navigation's content
            */
        Bar : function(config) {
            if (typeof MADE != "undefined") {
                return MADE;
            } else {
                MADE = this;
            }

            // privates
            var that = this,
                triggers = (config['triggers']) ? config.triggers : ['#vpro_nav_button'],
                templateClass = (config['style']) ? config.style : "",
                createLabel = (config['label']) ? (config['label']) : false,
                siteTeaserId = (config['site']) ? (config['site']) : null,
                listenToScroll = false,
                created = false,
                state = vpro.widget.Navigation.HIDDEN,
                searching = false,
                relatedInfo,
                container,
                label,
                button,
                wrap = TEMPLATE_WRAPS,
                overlay,
                searchInput,
                triggerApproach = config['triggerApproach'];

            function init() {
                if (typeof(window['$vpro']) == 'undefined') {
                    setTimeout(function(){
                        init();
                    }, 100);
                    return;
                }

                $vpro.noConflict();

                if (vpro.widget.Navigation.isIE6()){
                    vpro.widget.Navigation.includeIE6CSS();
                }

                if (createLabel) {
                    label = $vpro('<div id="vpro_nav_label"></div>');
                    $vpro('body').prepend(label);
                    triggers.push('#vpro_nav_label');
                }

                if(triggers.length > 0) {
                    if ($vpro(triggers.join(',')).length < triggers.length) {
                        setTimeout(function(){
                            init();
                        }, 50);
                        return;
                    }

                    $vpro.each(triggers, function(idx, value) {
                        initTrigger(value);

                        if(idx == 0) {
                            // should be the animated VPRO.nl logo img element
                            var b = $vpro(value);
                            if( b.length > 0 && b[0].nodeName.toLowerCase() == "img") {
                                button = new vpro.widget.Navigation.Button(b, triggerApproach);
                            }
                        }
                    });
                }
            }

            function createNavigationBar() {
                container = $vpro(getParsedTemplate(TEMPLATE_BAR, relatedInfo.get())).css('display', 'none');
                overlay = $vpro('<div id="vpro_nav_overlay"></div>').css('opacity', '0');
                searchInput = container.find('#vpro_nav_search input.query');

                if(searchInput.length > 0){
                    container.find('#vpro_nav_search').bind('submit', function(){
                        searching = true;
                    });

                    searchInput.bind('focus', function() {
                        searching = false;
                        if (/Zoeken/i.test(this.value)) {
                            this.value = '';
                        }
                    })
                    .bind('blur', function(){
                        var ref = $vpro(this);
                        setTimeout(function(){
                            if(!searching && !/Zoeken/i.test(ref[0].value)){
                                ref[0].value = 'Zoeken';
                            }
                        }, 100);
                    });
                }

                /** add it to the page */
                $vpro('body').prepend(overlay);
                $vpro('body').prepend(container);

                container.find('.vpro_nav_close').bind('click', function(){
                    toggle();
                    return false;
                });

                overlay.bind('click', function(){
                    toggle();
                });
            }

            function getRelatedItems(){

                var items = "";
                var relateds = relatedInfo.get();
                if(typeof relateds.associated != "undefined"){
                    items = getParsedTemplateForEach(TEMPLATE_RELATED_ITEM, relateds.associated);
                }
                return items;
            }


            function getTemplateProps(template){
                var props = {};
                var ps = template.match(/\{[^\}]+\}/g);
                $vpro.each(ps, function(idx, prop){
                    if(!props[prop]){
                        props[prop] = prop;
                    }
                });
                return props;
            }

            function getParsedTemplate(template, valueObj){
                var parsed = template;
                var props = getTemplateProps(parsed);

                $vpro.each(props, function(prop){

                    var r = new RegExp(prop,'gi');

                    parsed = parsed.replace(r, getProp(prop, (typeof valueObj != "undefined")? valueObj : {}));
                });
                return parsed;
            }

            //parse the given template for each entry in @param valueObjs and concatenate all
            function getParsedTemplateForEach(template, valueObjs){
                var parsed = "";
                var props = getTemplateProps(template);

                $vpro.each(valueObjs, function(idx, value){
                    var p = template;
                    $vpro.each(props, function(prop){
                        var r = new RegExp(prop,'gi');
                        p = p.replace(r, getProp(prop, (typeof value != "undefined")? value : {}));
                    });
                    parsed += p;
                });
                return parsed;
            }

            function getProp(prop, values) {
                switch(prop) {
                    case "{vpro_navigation_class}":
                        return ( (typeof values.style == "string")? values.style : templateClass);
                        break;

                    case "{related_categories}":
                        if(typeof values.poolName != "undefined"){
                            return values.poolName;
                        }
                        break;

                    case "{related_site}":
                        return ((typeof values.teaserTitle == "string")? values.teaserTitle : "" );
                        break;

                    case "{related_items}":
                        return getRelatedItems();
                        break;

                    case "{related_item_image}":
                        if(values.images.length > 0){

                            var first = values.images[0];
                            return (vpro.widget.Navigation.IMAGE_PATH + first.number);

                        }else if(typeof values.iconUrl == "string"){
                            return (values.iconUrl.split('+')[0]);
                        }
                        return "http://images.vpro.nl/img.db?42364138";
                        break;

                    case "{related_item_url}":
                        return ((typeof values.url == "string")? values.url : "" );
                        break;

                    case "{related_item_title}":
                        return ((typeof values.title == "string")? values.title : "" );
                        break;

                    case "{related_item_description}":
                        return ((typeof values.body == "string")? values.body : "" );
                        break;
                }
                return "";
            }

            function initTrigger(on) {
                vpro.widget.Navigation.stripClickHandler(on);

                var o = $vpro(on);
                if( o.length > 0) {
                    o.find('*').unbind('click');

                    o.find('a').bind('click', function(e) {
                        e.stopPropagation();
                        toggle();
                        return false;
                    });

                    o.bind('click', function() {
                        toggle();
                        return false;
                    });
                }
            }

            function clearTriggers(triggerOriginal) {
                var org;
                $vpro.each(triggers, function(idx, value){
                    removeTrigger(value);

                    if((triggerOriginal) && typeof org == "undefined"){

                        var h;
                        var t = $vpro(value);
                        if( t.length > 0){
                            //if an a element
                            if(/^a$/i.test(t[0].nodeName) && (typeof t.attr('href') != "undefined")){

                                h = t.attr('href');

                            //if has an a element child
                            }else if(t.find('//a[href]').length > 0){

                                h = t.find('//a[href]').eq(0).attr('href');

                            //if direct parent is an a element
                            }else if(t.parent().length > 0 && /^a$/i.test(t.parent()[0].nodeName) && (typeof t.parent().attr('href') != "undefined")){

                                h = t.parent().attr('href');
                            }
                            if(typeof h != "undefined"){
                                org = h;
                                document.location.href = h;
                            }
                        }
                    }
                });
            }

            function removeTrigger(of) {
                var o = $vpro(of);
                if( o.length > 0){
                    o.find('a').unbind('click');
                    o.unbind('click');
                }
            }

            function toggle() {
                if (state == vpro.widget.Navigation.HIDDEN) {
                    if (!created) {
                        if (typeof relatedInfo == "undefined") {
                            relatedInfo = new vpro.widget.Navigation.RelatedInfo({
                                site:(siteTeaserId)? siteTeaserId : null,
                                success : function(data) {
                                    created = true;
                                    createNavigationBar();
                                    toggle();
                                },
                                error: function(){
                                    clearTriggers(true);
                                }
                            });
                            relatedInfo.fetch();
                        }
                    } else {
                        reposition();

                        $vpro(window).bind('resize', function() {reposition();});
                        //toggleScrollListener(true);

                        vpro.widget.Navigation.toggleProblemObjectsVisibility(false);

                        container.show();
                        container.animate({ top: getPosition(true)/*, opacity:1 */}, "swing");

                        overlay.show();
                        overlay.fadeTo("swing", 0.4);

                        state = vpro.widget.Navigation.SHOWN;
                    }
                } else {
                    overlay.fadeOut("swing", function(){overlay.hide();});

                    container.animate({ top: getPosition(false)/*, opacity:0 */}, "swing", function(){
                        container.hide();

                        $vpro(window).unbind('resize', function() {
                            reposition();
                        });

                        vpro.widget.Navigation.toggleProblemObjectsVisibility(true);
                    });


                    state = vpro.widget.Navigation.HIDDEN;
                }
            }

            function toggleScrollListener(on) {
                if (on) {
                    listenToScroll = true;
                    $vpro(document).bind('scroll', function() {
                        position(true);
                    });
                }else {
                    listenToScroll  = false;
                    $vpro(document).unbind('scroll', function() {
                        position(true);
                    });
                }
            }

            function reposition() {
                var bw = $vpro('body').innerWidth();
                var bhi = vpro.widget.Navigation.getInnerHeight();
                var bh = $vpro('body').innerHeight();
                    bh = (bh > bhi)? bh : bhi;

                if (bw < vpro.widget.Navigation.MIN_WIDTH) {
                    container.addClass(vpro.widget.Navigation.CLASS_OVERFLOW);
                    container.width(vpro.widget.Navigation.MIN_WIDTH);
                    $vpro.each(wrap, function() {
                        container.find(this).width(vpro.widget.Navigation.MIN_WIDTH);
                    });
                    overlay.width(vpro.widget.Navigation.MIN_WIDTH);
                } else if (bw > vpro.widget.Navigation.MAX_WIDTH) {
                    container.removeClass(vpro.widget.Navigation.CLASS_OVERFLOW);
                    container.width(bw);
                    $vpro.each(wrap, function() {
                        container.find(this).width(vpro.widget.Navigation.MAX_WIDTH);
                    });
                    overlay.width(bw);
                } else {
                    container.removeClass(vpro.widget.Navigation.CLASS_OVERFLOW);
                    container.width(bw);
                    $vpro.each(wrap, function() {
                        $vpro.find(this).width(bw);
                    });
                    overlay.width(bw);
                }

                overlay.height(bh);

                if (state == vpro.widget.Navigation.HIDDEN) {
                    position(false);
                } else {
                    position(true);
                }
            }

            function position(shown) {
                var top = 0;
                    top += (listenToScroll)? $vpro(document).scrollTop() : 0;

                if(!shown){
                    top -= container.outerHeight();
                }
                container.css('top', top);
            }

            function getPosition(shown) {
                var top = 0;
                    top += (listenToScroll)? $vpro(document).scrollTop() : 0;
                if(!shown){
                    top -= container.outerHeight();
                }
                return top;
            }

            // priviliged | public
            this.addTrigger = function(trigger) {
                if($vpro.inArray(trigger, triggers) == -1 && $vpro(trigger).length > 0){
                    triggers.push(trigger);
                    initTrigger(trigger);
                }
            }

            // fire away
            vpro.widget.Navigation.includeCss(vpro.widget.Navigation.ASSET_CSS);

            init();
        }, // BAR


        /**
            * For the given or current URL return an info object with related VPRO sites and info.
            *
            * @param c Hash of options
            *        @option href String location to get related info on
            *                @default current document location
            *        @option success Function to call on successful fetch of related info
            *        @option error Function to call on an error while fetching related info
            *        @option site Number id of a VPRO site teaser as used on http://www.vpro.nl/a-z-index
            *                if provided will be used to get related info on, if not provided will fall back to href option
            */
        RelatedInfo : function(c) {
            // privates
            var that = this,
                info = {},
                href = (c.href) ? c.href : document.location.href,
                onSuccess = (c.success) ? c.success : function(){},
                onError = (c.error) ? c.error : function(){},
                site = (c.site) ? c.site : null;

            // private
            function checkDataIntegrity(data) {
                if(typeof data.teaserTitle != "undefined" && typeof data.associated != "undefined"){
                    return true;
                }
                return false;
            }

            // priviliged
            this.get = function() {
                return info;
            };

            this.fetch = function() {
                var url = vpro.widget.Navigation.RELATED_DATA_URL;
                    url = url.replace('{site}', (site)? site : '');
                    url = url.replace('{referrer}', (!site)? encodeURI(document.location.href) : '');

                $vpro.ajax({
                    url : url,
                    dataType : "jsonp",
                    success : function(data) {
                        if (checkDataIntegrity(data)) {
                            info = data;
                            onSuccess(info);
                        } else {
                            onError();
                        }
                    }
                });

                // because of JSONP set our own FAIL timeout
                setTimeout(function(){
                    if (!checkDataIntegrity(info)) {
                        onError();
                    }
                }, 2500);
            };

        },

        /**
            * The specific animated button that will trigger the Navigation.
            *
            * @param img jQuery BUTTON_1 image
            * @param distance Number of pixels for near animations will be triggered
            *            defaults to 100
            */
        Button : function(img, distance) {
            // privates
            var hover = false,
                nearDist = (typeof distance == "number")? distance : 100,
                isIE6 = vpro.widget.Navigation.isIE6(),
                center = {};

            var button = img;
            var button_1         = new Image();
                button_1.src     = button[0].src;
                button_1.id     = vpro.widget.Navigation.BUTTON_1;
            var button_2         = new Image();
                button_2.id        = vpro.widget.Navigation.BUTTON_2;
                button_2.src     = button[0].src.replace(vpro.widget.Navigation.BUTTON_1, vpro.widget.Navigation.BUTTON_2);
            var button_3         = new Image();
                button_3.id        = vpro.widget.Navigation.BUTTON_3;
                button_3.src     = button[0].src.replace(vpro.widget.Navigation.BUTTON_1, vpro.widget.Navigation.BUTTON_3);

            function approach(to){
                if(!hover){
                    if(isIE6 && !(new RegExp(""+ to.id)).test(button[0].style.filter)){
                        changeSource(to.src);
                    }else if(button[0].src != to.src){
                        changeSource(to.src);
                    }
                }
            }

            function changeSource(to){
                if(isIE6){
                    button[0].src = to;
                    button[0].style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + to + "', sizing='scale')";
                }else{
                    button[0].src = to;
                }
            }

            // go go go
            var offset = button.offset();
            center = { x: (offset.left + (button.width()/2)), y: (offset.top + (button.height()/2)) };

            if(isIE6) {
                vpro.widget.Navigation.fixImageForIE(button[0]);
            }

            button.bind('mouseover', function(){
                hover = true;
                changeSource(button_3.src);
            }).bind('mouseout', function(){
                hover = false;
                changeSource(button_2.src);
            });


            $vpro().mousemove(function(e){
                var distance = parseInt(Math.sqrt(Math.pow(e.pageX-center.x,2) + Math.pow(e.pageY-center.y,2)));

                if (distance <= nearDist) {
                    approach(button_2);
                } else {
                    approach(button_1);
                }
            });
        },

        /***************************************************************
            * Static Utils
            * @inspired ;) NPO Ontdek Omroep.nl, thanx guys
            **************************************************************/

        includeScript : function(scriptName) {
            var js = document.createElement('script');
                js.setAttribute('language', 'javascript');
                js.setAttribute('type', 'text/javascript');
                js.setAttribute('src', scriptName);
            var headElement = document.getElementsByTagName('head').item(0);
                headElement.appendChild(js);
            return false;
        },

        includeCss :function(url) {
            var stylesheet = document.createElement('link');
                stylesheet.setAttribute('rel', 'stylesheet');
                stylesheet.setAttribute('href', url);
                stylesheet.setAttribute('type', 'text/css');
                stylesheet.setAttribute('media', 'screen');
                stylesheet.setAttribute('charset', 'utf-8');
            var htmlDoc = document.getElementsByTagName('head').item(0);
                htmlDoc.appendChild(stylesheet);
            return false;
        },

        stripClickHandler: function(of) {
            $vpro(of).get(0).onclick = '';
        },

        isIE6: function() {
            return($vpro.browser.msie && Number($vpro.browser.version) >= 6 &&  Number($vpro.browser.version) < 7);
        },

        includeIE6CSS: function() {
            if (vpro.widget.Navigation.isIE6()) {
                vpro.widget.Navigation.includeCss(vpro.widget.Navigation.ASSET_CSS_IE6);
            }
        },

        fixImageForIE: function(img) {
            if (vpro.widget.Navigation.isIE6()) {
                img.style.paddingTop = (img.height +"") + "px";
                img.style.overflow = "hidden";
                img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + img.src + "', sizing='scale')";
            }
        },

        toggleProblemObjectsVisibility: function(visible) {
            //toont of verbergt problematische objecten (flash, selectfields)
            //ook voor alle iframes
            var vis = (visible === false) ? "hidden" : "visible";
            $vpro("select,object,embed").css("visibility", vis);
            $vpro("iframe").css("visibility", vis);
        },

        getInnerHeight : function(){
            if (self.innerHeight) {
                return self.innerHeight;
            } else if (document.documentElement && document.documentElement.clientHeight) {
                return document.documentElement.clientHeight;
            } else if (document.body) {
                return document.body.clientHeight;
            } else {
                return 0;
            }
        },

        getInnerWidth : function(){
            if(self.innerWidth) {
                return self.innerWidth;
            } else if (document.documentElement && document.documentElement.clientWidth) {
                return document.documentElement.clientWidth;
            } else if (document.body) {
                return document.body.clientWidth;
            } else {
                return 0;
            }
        }
    };

    vpro.widget.Navigation.includeScript(vpro.widget.Navigation.ASSET_JQUERY);
})();
} // if (!window.vpro.widget.Navigation && !window.$vpro)
