$(function() {
    
    /* DBPEDIA OVERLAY */
    
    var lang = $("html").attr("lang"),
        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,
        dontclose = false,
        $refdiv = null,
        $win = $(window),
        dbpediaCache = {},
        $overlayImg = $overlay.find("img"),
        $h2 = $overlay.find("h2"),
        $abstract = $overlay.find(".dbpedia-abstract"),
        $source = $overlay.find(".dbpedia-source a");
        
    window.moveDbpediaBoxToCoords = function(x, y, ymargin, alwaysbelow) {
        var ovw = $overlay.outerWidth(),
            ovh = $overlay.outerHeight(),
            showAbove = (y + ymargin + ovh) > ($win.height() + $win.scrollTop()) && !alwaysbelow;
        $overlay.css({
            top: showAbove ? (y - ovh - ymargin) : (y + ymargin),
            left: Math.max(5, Math.min($win.width() - ovw - 5, x - (ovw / 2)))
        });
    }
    
    function moveDbpediaBoxToRefDiv() {
        if (hovering && $refdiv) {
            var refoff = $refdiv.offset(),
                refw = $refdiv.outerWidth(),
                refh = $refdiv.outerHeight(),
                refx = refoff.left,
                refy = refoff.top;
            window.moveDbpediaBoxToCoords(refx + (refw / 2), refy + (refh / 2), refh / 2);
        }
    }
    
    window.showDbpediaBox = function(dbpediaUri, cancelClose) {
        if (!dbpediaUri) {
            return;
        }
        dontclose = cancelClose || false;
        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);
        moveDbpediaBoxToRefDiv();
    }
    
    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) {
                window.showDbpediaBox(dbpediaUri);
            }
        });
    }
        
    window.hideDbpediaBox = function() {
        hovering = null;
        setTimeout(function() {
            if (!hovering) {
                $overlay.hide();
                deferredRemovePopin();
                $refdiv = null;
            }
        }, 0);
    }
    
    window.bindDbpediaBox = function(selector, defaultUri) {
        var $sel = $(selector);
        $sel.off("mouseenter mouseleave");
        $sel.mouseenter(function(e) {
            $refdiv = $(this);
            var dbpediaUri = $refdiv.attr("data-dbpedia-uri") || defaultUri;
            if (!dbpediaUri || dbpediaUri === "None") {
                return;
            }
            window.showDbpediaBox(dbpediaUri);
        });
        $sel.mouseleave(window.hideDbpediaBox);
    }    
        
    $overlay.hover(function() {
        var $this = $(this),
            dbpediaUri = $this.attr("data-dbpedia-uri");
        if (dbpediaUri) {
            hovering = dbpediaUri;
        }
    }, function() {
        if (!dontclose) {
            window.hideDbpediaBox();
        }
    });
    
    /* END DBPEDIA OVERLAY MANAGEMENT */
   
    /* NOTICE LIST MANAGEMENT */
   
    var gridsize = 160,
        $popin = null,
        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 = $tblist.children(":first").width() || 160;
            $tblist.css({
                padding: "0 " + Math.floor($tblist.parent().width() % gridsize / 2) + "px"
            });
        }
        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],
                ih = img.height;
            if (ih < 30) {
                notloaded = true;
                return;
            }
            var iw = img.width,
                scale = 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, 500);
        }
    }
    
    var throttledCheckSizes = _(checkSizes).throttle(200);
    
    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();
    }
    
    $win.resize(function() {
        adaptGrid();
        moveDbpediaBoxToRefDiv();
    }).scroll(moveDbpediaBoxToRefDiv);
        
    $(".language-label").click(function() {
       $(this).siblings(".language-button").click(); 
    });
/*
    $(".language-current").click(function() {
        $(".language-list").toggle();
    });
*/    
    $overlayImg.load(moveDbpediaBoxToRefDiv);
    
});
