/* Image load events may be triggered before jQuery is loaded.
 * Here we bind temporary functions to the Window namespace */

(function() {
    
    function tmpBind(property) {
        window[property] = function() {
            var arglist = Array.prototype.slice.call(arguments);
            setTimeout(function() {
                window[property].apply(window, arglist);
            }, 500);
        };
    }
    
    var propsToBind = [ "onWikiImageLoad", "onWikiImageError", "onResultImageError" ];
    for (var i = 0; i < propsToBind.length; i++) {
        tmpBind(propsToBind[i]);
    }
    
})();

$(function() {
    
    /* SEARCH TAG-IT */
   
    var $searchInput = $(".search-input"),
        originalValue = $searchInput.val(),
        allowSubmit = false;
    
    function submitIfChanged(e, ui) {
        var val = $searchInput.val();
        if (allowSubmit && val && val !== originalValue) {
            $(".search-form").submit();
        }
    }
    
    $searchInput.tagit({
        autocomplete: {
            source: urls.ajax_terms,
            focus: function(e, ui) {
                showDbpediaBox(ui.item.dbpedia_uri);
                setDbpediaBoxAnchor({type: "dom", selector: $(e.target).autocomplete("widget"), positioning: "side"});
            }
        },
        allowSpaces: true,
        afterTagAdded : submitIfChanged,
        afterTagRemoved: submitIfChanged,
        singleFieldDelimiter: ";"
    });
    allowSubmit = true;
    
    /* END SEARCH TAG-IT */
    
    /* DBPEDIA OVERLAY */
    
    var lang = $("html").attr("lang").substr(0,2) || "fr",
        sparqlTpl = _.template(
            'select distinct * where { '
            + 'OPTIONAL { <<%= uri %>> rdfs:label ?l FILTER( langMatches( lang(?l), "<%- lang %>" ) ) }. '
            + 'OPTIONAL { <<%= uri %>> dbpedia-owl:thumbnail ?t }. '
            + 'OPTIONAL { <<%= uri %>> dbpedia-owl:abstract ?a FILTER( langMatches( lang(?a), "<%- lang %>" ) ) }. '
            + 'OPTIONAL { <<%= uri %>> dbpedia-owl:wikiPageRedirects ?r }. '
            + 'OPTIONAL { ?r rdfs:label ?lr FILTER( langMatches( lang(?lr), "<%- lang %>" ) ) }. '
            + 'OPTIONAL { ?r dbpedia-owl:thumbnail ?tr }. '
            + 'OPTIONAL { ?r dbpedia-owl:abstract ?ar FILTER( langMatches( lang(?ar), "<%- lang %>" ) ) }. '
            + '}'
        ),
        $overlay = $(".dbpedia-overlay"),
        hovering = null,
        anchor = null,
        $win = $(window),
        dbpediaCache = {},
        $overlayImg = $overlay.find("img"),
        $h2 = $overlay.find("h2"),
        $abstract = $overlay.find(".dbpedia-abstract"),
        $source = $overlay.find(".dbpedia-source a");
    
    function setDbpediaBoxAnchor(a) {
        anchor = a || null;
        if (anchor) {
            recentreDbpediaBox();
        }
    }
    
    function recentreDbpediaBox() {
        if (!anchor) { return; }
        var ovw = $overlay.outerWidth(),
            ovh = $overlay.outerHeight(),
            refbox;
        switch (anchor.type) {
            case "dom":
                var $refdiv = anchor.selector,
                    refoff = $refdiv.offset(),
                    refw = $refdiv.outerWidth(),
                    refh = $refdiv.outerHeight(),
                    refx = refoff.left,
                    refy = refoff.top;
                refbox = { left: refx, right: refx + refw, top: refy, bottom: refy + refh };
            break;
            case "box":
                refbox = anchor.box;
            break;
            case "callback":
                refbox = anchor.callback();
            break;
        }
        if (!refbox) { return; }
        if (!refbox.right) { refbox.right = refbox.left; }
        if (!refbox.bottom) { refbox.bottom = refbox.top; }
        refbox.hcentre = (refbox.left + refbox.right) / 2;
        switch (anchor.positioning) {
            case "side":
                var showLeft = (refbox.right + ovw) > $win.width();
                css = { left: showLeft ? (refbox.left - ovw) : (refbox.right), top: refbox.top };
            break;
            case "bottom":
                css = { left: refbox.hcentre - ovw / 2, top: refbox.bottom };
            break;
            case "vertical":
            default:
                var showAbove = (refbox.bottom + ovh) > ($win.height() + $win.scrollTop());
                css = { left: refbox.hcentre - ovw / 2, top: showAbove ? refbox.top - ovh : refbox.bottom };
        }
        if (css) {
            css.left = Math.max(5, Math.min($win.width() - ovw - 5, css.left));
            $overlay.css(css);
        }
    }
        
    function showDbpediaBox(dbpediaUri) {
        if (!dbpediaUri) {
            return;
        }
        hovering = dbpediaUri;
        $overlay.hide();
        $overlayImg.attr("src","");
        var uriData = dbpediaCache[dbpediaUri];
        if (!uriData) {
            getUriData(dbpediaUri);
            return;
        }
        $overlay.show().attr("data-dbpedia-uri", dbpediaUri);
        if (uriData.t || uriData.tr) {
            $overlayImg.attr("src",uriData.t || uriData.tr).show();
        } else {
            $overlayImg.hide();
        }
        var label = uriData.l || uriData.lr || "",
            wkUrl = "http://" + lang + ".wikipedia.org/";
        if (label) {
            wkUrl += "wiki/" + encodeURI(label.replace(/ /g,'_'));
        } 
        $h2.text((uriData.l && uriData.lr) ? (uriData.l + " → " + uriData.lr) : label);
        $abstract.text((uriData.a || uriData.ar || "").replace(/^(.{240,260})\s.+$/,'$1…').substr(0,261));
        $source.attr("href", wkUrl);
        recentreDbpediaBox();
    }
    
    function getUriData(dbpediaUri) {
        if (typeof dbpediaCache[dbpediaUri] !== "undefined") {
            return;
        }
        var sparqlEndpoint = dbpediaUri.replace(/\/resource\/.*$/,'/sparql'),
            query = sparqlTpl({uri: decodeURI(dbpediaUri), lang: lang});
        dbpediaCache[dbpediaUri] = false;
        $.getJSON(sparqlEndpoint, {
            query: query,
            format: "application/sparql-results+json"
        }, function(data) {
            if (!data.results || !data.results.bindings || !data.results.bindings.length) {
                return;
            }
            var res = data.results.bindings[0], cacheData = {};
            for (var k in res) {
                if (res.hasOwnProperty(k)) {
                    cacheData[k] = res[k].value;
                }
            }
            dbpediaCache[dbpediaUri] = cacheData;
            if (hovering === dbpediaUri) {
                showDbpediaBox(dbpediaUri);
            }
        });
    }
        
    function hideDbpediaBox() {
        hovering = null;
        setTimeout(function() {
            if (!hovering) {
                $overlay.hide();
                setDbpediaBoxAnchor();
                deferredRemovePopin();
            }
        }, 0);
    }
    
    function bindDbpediaBox(selector, defaultUri) {
        var $sel = $(selector);
        $sel.off("mouseenter mouseleave");
        $sel.mouseenter(function(e) {
            var $this = $(this);
            setDbpediaBoxAnchor({ selector: $this, type: "dom", positioning: "vertical" });
            var dbpediaUri = $this.attr("data-dbpedia-uri") || defaultUri;
            if (!dbpediaUri || dbpediaUri === "None") {
                return;
            }
            showDbpediaBox(dbpediaUri);
        });
        $sel.mouseleave(hideDbpediaBox);
    }
        
    $overlay.hover(function() {
        var $this = $(this),
            dbpediaUri = $this.attr("data-dbpedia-uri");
        if (dbpediaUri) {
            hovering = dbpediaUri;
        }
    }, hideDbpediaBox);
    
    $overlay.find(".dbpedia-close").click(function() {
        hideDbpediaBox();
        return false;
    });
    
    window.dbpediaBox = {
        bind: bindDbpediaBox,
        hide: hideDbpediaBox,
        show: showDbpediaBox,
        setAnchor: setDbpediaBoxAnchor,
        recentre: recentreDbpediaBox
    };
    
    /* END DBPEDIA OVERLAY MANAGEMENT */
   
    /* NOTICE LIST MANAGEMENT */
   
    var gridsize = 160,
        $popin = null,
        $results = $(".results"),
        hoverPopin = false;
    
    function removePopin() {
        if ($popin) {
            $(".notice-item").removeClass("notice-hover");
            $popin = null;
        }
    }  
    
    function deferredRemovePopin() {
        window.setTimeout(function() {
            if (!hoverPopin) {
                removePopin();
            }
        }, 0);
    }
            
    function adaptGrid() {
        var $tblist = $(".notice-list");
        if ($tblist.length) {
            gridsize = $(".notice-item").width() || 160;
            var outerw = $results.width(),
                delta = outerw % gridsize,
                innerw = outerw - delta,
                p = Math.floor(delta/2);
            $tblist.css({
                padding: "0 " + p + "px"
            });
            var $wikinfo = $(".wiki-info");
            if ($wikinfo.length) {
                var wkw = Math.min(3*gridsize, innerw),
                    wkh = 2*gridsize;
                $wikinfo.css({
                    width: wkw + "px",
                    height: wkh + "px"
                });
                $wikinfo.find(".wiki-info-image").css({
                    "max-width": (wkw / 2 - 10) + "px",
                    "max-height": wkh - 20
                });
            }
        }
        throttledCheckSizes();
    }
    
    function checkSizes() {
        var notloaded = false;
        $(".notice-item").each(function() {
            var $this = $(this),
                $nc = $(this).find(".notice-contents"),
                $img = $(this).find(".notice-image"),
                $md = $(this).find(".notice-metadata"),
                img = $img[0],
                iw = img.width,
                ih = img.height;
            if (!img.complete || iw < 30 || ih < 30) {
                notloaded = true;
                return;
            }
            var scale = Math.min(2, gridsize / Math.min(iw, ih)),
                nw = scale * iw,
                nh = scale * ih,
                ww = $win.width(),
                isleft = ($this.offset().left + gridsize / 2 < ww / 2),
                isfull = (nw > ww - 300);
            $img.css({
                width: nw + "px",
                height: nh + "px",
                float: isleft ? "left": "right"
            });
            $md.css({
                "margin-left" : (isleft && !isfull) ? nw + 10 : 0,
                "margin-right" : (!isleft && !isfull) ? nw + 10 : 0
            });
            $nc.css({
                left: isleft ? "0" : "",
                right: isleft ? "" : "0",
                width: isfull ? nw : (nw + 260),
                "margin-top": ((gridsize - nh) / 3 - 10) + "px",
                "margin-left": isleft ? ((gridsize - nw) / 2 - 10) + "px" : 0,
                "margin-right": isleft ? 0 : ((gridsize - nw) / 2 - 10) + "px"
            });
        });
        if (notloaded) {
            setTimeout(throttledCheckSizes, 800);
        }
    }
    
    var throttledCheckSizes = _(checkSizes).throttle(500);
    
    window.bindResultsMouseover = function() {
        var $items = $(".notice-item");
        $items.off("mouseenter mouseover");
        $items.mouseenter(function() {
            var $this = $(this);
            hoverPopin = true;
            if ($popin && $popin === $this) {
                return;
            }
            removePopin();
            if (!$this.find(".notice-image")[0].width) {
                return;
            }
            $popin = $this;
            $this.addClass("notice-hover");
        });
        $items.mouseleave(function() {
            hoverPopin = false;
            if ($overlay.is(":hidden")) {
                deferredRemovePopin();
            }
        });
        bindDbpediaBox($items.find(".notice-term a"));
        adaptGrid();
    };
    
    window.onResultImageError = function(img) {
        img.src = urls.img_if_404;
        throttledCheckSizes();
    };
    
    /* END NOTICE LIST MANAGEMENT */
    
    /* AJAX SCROLL LOAD */
    
    var max_scroll_pages = 3, currentpage;
    
    function loadMorePages(query) {
        $(".load-more").hide();
        $win.off("scroll.ajaxload");
        $(".notice-list").empty();
        $(".loading-please-wait").show();
        currentpage++;
        $(".notice-list").attr("data-current-page", currentpage);
        $.ajax({
            url: urls.ajax_search,
            data: _({ page: currentpage }).extend(query),
            dataType: "html",
            success: function(html) {
                $(".notice-list").html(html);
                bindResultsMouseover();
                $(".loading-please-wait").hide();
                scrollLoad(query);
            }
        });
    }
    
    window.scrollLoad = function(query) {
        currentpage = parseInt($(".notice-list").attr("data-current-page"));
        var loadingnext = false,
            page_count = parseInt($(".notice-list").attr("data-page-count")),
            max_page = Math.min(currentpage + max_scroll_pages, page_count);
        $(".load-more").hide().off("click").click(function() {
            loadMorePages(query);
            return false;
        });
        $win.on("scroll.ajaxload", function() {
            if (loadingnext || currentpage >= max_page) {
                return;
            }
            var $datablock = $(".notice-list"),
                winbottom = $win.scrollTop() + $win.height(),
                databottom = $datablock.offset().top + $datablock.height();
            if (winbottom >= databottom) {
                loadingnext = true;
                $(".loading-please-wait").show();
                $.ajax({
                    url: urls.ajax_search,
                    data: _({ page: ++currentpage }).extend(query),
                    dataType: "html",
                    success: function(html) {
                        $datablock.append(html);
                        loadingnext = false;
                        bindResultsMouseover();
                        $(".loading-please-wait").hide();
                        if (currentpage >= max_page && currentpage < page_count) {
                            $(".load-more").show();
                        }
                    }
                });
            }
        });
    };
    
    window.loadSearchResults = function(query) {
        $(".hide-on-search").hide();
        $win.off("scroll.ajaxload");
        $(".wiki-info img").off("load error");
        $results.empty();
        $(".loading-please-wait").show();
        $.ajax({
            url: urls.ajax_search,
            data: query,
            dataType: "html",
            success: function(html) {
                $results.html(html);
                bindResultsMouseover();
                $(".loading-please-wait").hide();
                scrollLoad(query);
                resizeWikiInfo();
            }
        });
    };
    
    /* Resizing text in the wikipedia abstract in search results */
    
    var currentAbstract, currentUri, currentW, currentH;
    
    function resizeWikiInfo(force) {
        var $wikinfo = $(".wiki-info");
        if (!$wikinfo.length) {
            return;
        }
        var uri = $wikinfo.attr("data-dbpedia-uri"), w = $wikinfo.width(), h = $wikinfo.height(), $wiabstract = $wikinfo.find(".wiki-info-abstract");
        if (uri === currentUri) {
            if (w === currentW && h === currentH && !force) {
                return;
            }
        } else {
            currentUri = uri;
            currentAbstract = $wiabstract.text();
        }
        currentW = w;
        currentH = h;
        var leftSpace = h - ($wikinfo.find(".wiki-info-title").outerHeight(true) + $wikinfo.find(".wiki-info-source").outerHeight(true));
        $wiabstract.text(currentAbstract);
        var shortenedAbstract = currentAbstract;
        while ($wiabstract.height() > leftSpace) {
            shortenedAbstract = shortenedAbstract.replace(/\s[\S]+$/,'…');
            $wiabstract.text(shortenedAbstract);
        }
    }
    
    resizeWikiInfo();
    
    window.onWikiImageLoad = function() {
        resizeWikiInfo(true);
    };
    window.onWikiImageError = function(img) {
        $(img).hide();
        resizeWikiInfo(true);
    };
    
    /* */
    
    $win.resize(function() {
        adaptGrid();
        recentreDbpediaBox();
        resizeWikiInfo();
    }).scroll(recentreDbpediaBox);
    
    $overlayImg.load(recentreDbpediaBox);
    
    var hideTo, $mm = $(".main-menu");
    
    function hideMenu() {
        clearTimeout(hideTo);
        hideTo = setTimeout(function() {
            $mm.stop(true).slideUp();
        }, 3000);
    }
    function showMenu(selector) {
        clearTimeout(hideTo);
        $mm.stop(true).slideDown();
    }
    $(".main-menu-link").mouseenter(showMenu).mouseleave(hideMenu).click(function() {
        $mm.stop(true).slideToggle();
        return false;
    });
    
    $mm.mouseover(showMenu).mouseout(hideMenu);
    
    $(".language-menu-link").click(function() {
        $(".language-menu").slideToggle();
    });
    
    $(".language-menu a").click(function() {
        $(".language-input").val($(this).attr("data-language-code"));
        $(".language-form").submit();
        return false;
    });
    
});
