$(function() {
    
    /* SEARCH TAG-IT */
   
    var $searchInput = $(".search-input"),
        originalValue = $searchInput.val();
    
    function submitIfChanged(e, ui) {
        var val = $searchInput.val();
        if (!ui.duringInitialization && 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
    });
    
    /* 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,
        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();
        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 "callback":
                var 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, 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);
        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;
        }
    }, function() {
        if (!dontclose) {
            hideDbpediaBox();
        }
    });
    
    window.dbpediaBox = {
        bind: bindDbpediaBox,
        hide: hideDbpediaBox,
        show: showDbpediaBox,
        setAnchor: setDbpediaBoxAnchor,
        recentre: recentreDbpediaBox
    }
    
    /* 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();
    }
    
    /* AJAX SCROLL LOAD */
    
    var max_scroll_pages = 3;
    
    window.scrollLoad = function(data) {
        var loadingnext = false,
            currentpage = parseInt($(".notice-list").attr("data-current-page")),
            page_count = parseInt($(".notice-list").attr("data-page-count")),
            max_page = Math.min(currentpage + max_scroll_pages, page_count),
            margin = 20;
        $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 - margin) {
                loadingnext = true;
                $(".loading-please-wait").show();
                $.ajax({
                    url: urls.ajax_search,
                    data: _({ page: ++currentpage }).extend(data),
                    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().find("a").attr("href",
                                urls.ajax_search + "?" + $.param(_({ page: currentpage + 1 }).extend(data))
                            );
                        }
                    }
                });
            }
        });
    }
    
    window.loadContentsByUri = function(dbpedia_uri) {
        $win.off("scroll.ajaxload");
        $(".results").empty();
        $.ajax({
            url: urls.ajax_search,
            data: {
                dbpedia_uri: dbpedia_uri
            },
            dataType: "html",
            success: function(html) {
                $(".results").html(html);
                bindResultsMouseover();
                scrollLoad({ dbpedia_uri: dbpedia_uri });
            }
        });
    }
    /* */
    
    
    $win.resize(function() {
        adaptGrid();
        recentreDbpediaBox();
    }).scroll(recentreDbpediaBox);
    
    $overlayImg.load(recentreDbpediaBox);
    
    $(".menu-link a").mouseover(function() {
        var $menu = $($(this).attr("href"));
        $menu.stop(true).slideDown(function(){ $menu.css("height",""); });
    }).mouseout(function() {
        var $menu = $($(this).attr("href"));
        $menu.stop(true).delay(3000).slideUp(function(){ $menu.css("height",""); });
    }).click(function() {
        return false;
    });
    
    $(".menu-list").mouseover(function() {
        $menu = $(this);
        $menu.stop(true).show().css("height","");
    }).mouseout(function() {
        $menu = $(this);
        $menu.stop(true).delay(3000).slideUp(function(){ $menu.css("height",""); });
    });
    
    $("#language-menu a").click(function() {
        $(".language-input").val($(this).attr("data-language-code"));
        $(".language-form").submit();
        return false;
    });
    
});
