$(function() {
        
    $('.notice-images a').magnificPopup({type:'image'});
    dbpediaBox.bind(".notice-term a");
    
    var lang = document.querySelector("html").lang.substr(0,2) || "fr",
        labelsCache = {},
        dbpCache = {},
        eventCache = {},
        errorCache = {};
        
    var frSparqlTpl = _.template(
        'select distinct * where { ?s rdfs:label "<%= label %>"@<%= lang %> . '
        + 'OPTIONAL { ?s rdfs:label ?l. ?s dbpedia-owl:abstract ?a. FILTER(lang(?a)=lang(?l)) }. '
        + 'OPTIONAL { ?s dbpedia-owl:thumbnail ?t }. OPTIONAL { ?s dbpedia-owl:wikiPageRedirects ?r }.' 
        + 'OPTIONAL { ?r rdfs:label ?lr. ?r dbpedia-owl:abstract ?ar FILTER(lang(?ar)=lang(?lr)) }. '
        + 'OPTIONAL { ?r dbpedia-owl:thumbnail ?tr }. '
        + 'FILTER(!regex(?s, ":[^/]+$" ) && regex(?s, "^http://fr.dbpedia.org/resource/")) }'
//        + 'OPTIONAL { ?s dbpedia-owl:wikiPageDisambiguates ?d }. OPTIONAL { ?d rdfs:label ?ld FILTER( langMatches( lang(?ld), "en" ) ) }. '
    );
    
    var otherSparqlTpl = _.template(
        'select distinct * where { '
        + '?s foaf:isPrimaryTopicOf <<%= wikipedia_url %>>. '
        + 'OPTIONAL { ?s dbpedia-owl:wikiPageRedirects ?r }. '
        + 'OPTIONAL { ?s rdfs:label ?l . ?s dbpedia-owl:abstract ?a . FILTER(lang(?l)=lang(?a)) }. ' 
        + 'OPTIONAL { ?s dbpedia-owl:thumbnail ?t }. '
        + 'OPTIONAL { ?r rdfs:label ?lr . ?r dbpedia-owl:abstract ?ar . FILTER(lang(?lr)=lang(?ar)) }. '
        + 'OPTIONAL { ?r dbpedia-owl:thumbnail ?tr }. '
        + '}'
    );
        
    function getDbpedia(label, callback, errorcb) {
        
        function onBindingsLoaded(sparqlData, initialData) {
            var bindings = sparqlData.results.bindings,
                res = initialData || {};
            res.translations = _(sparqlData.results.bindings).map(function(b) {
                var t = {}
                t.dbpedia_uri = b.s.value;
                if (b.r) { t.dbpedia_uri = b.r.value; }
                if (b.a) { t.abstract = b.a.value; }
                if (b.ar) { t.abstract = b.ar.value; }
                if (b.t) { t.thumbnail = b.t.value; }
                if (b.tr) { t.thumbnail = b.tr.value; }
                if (b.l) {
                    t.label = b.l.value;
                    t.language = b.l["xml:lang"];
                }
                if (b.lr) {
                    t.label = b.lr.value;
                    t.language = b.lr["xml:lang"];
                }
                if (!t.label) {
                    t.label = label;
                }
                if (!t.language) {
                    t.language = lang;
                }
                return t;
            });
            res.local = _(res.translations).find(function(t) {
                return t.language === lang;
            }) || {};
            res.label = res.local.label || label;
            res.dbpedia_uri = res.translations[0].dbpedia_uri;
            res.wikipedia_url = "http://" + lang + ".wikipedia.org/wiki/" + encodeURIComponent(res.label.replace(/ /g,'_'));
            dbpCache[label] = res;
            _(eventCache[label]).each(function(cb) {
                cb(label, res);
            });
            delete eventCache[label];
            if (res.label !== label) {
                dbpCache[res.label] = res;
                _(eventCache[res.label]).each(function(cb) {
                    cb(res.label, res);
                });
                delete eventCache[res.label];
            }
        }
        
        function onError() {
            dbpCache[label] = false;
            _(errorCache[label]).each(function(cb) {
                cb(label);
            });
            delete errorCache[label];
        }
        
        if (dbpCache[label]) {
            //console.log("Data already in cache", dbpCache[label]);
            if (typeof callback === "function") { callback(label, dbpCache[label]); }
            return;
        }
        if (dbpCache[label] === false) {
            if (typeof errorcb === "function") { errorcb(label); }
            return;
        }
        if (typeof eventCache[label] === "undefined") {
            eventCache[label] = [];
            errorCache[label] = [];
        }
        if (typeof callback === "function") { eventCache[label].push(callback); }
        if (typeof errorcb === "function") { errorCache[label].push(callback); }
                
        if (typeof dbpCache[label] === "undefined") {
            dbpCache[label] = null;
            $.ajax({
                url: urls.wikipedia.fr.dbpedia_sparql_url,
                data: {
                    query: frSparqlTpl( { label: label, lang: lang } ),
                    format: "application/sparql-results+json"
                },
                dataType: "json",
                success: function(data) {
                    if (data.results.bindings.length) {
                        //console.log("Data found in french DbPedia", data.results.bindings[0]);
                        onBindingsLoaded(data, { dbpedia_language: "fr" });
                    } else {
                        if (lang !== "fr" && urls.wikipedia[lang]) {
                            var wk_url = urls.wikipedia[lang].page_url + '/' + encodeURIComponent(label.replace(/ /g,'_'));
                            $.ajax({
                                url: urls.wikipedia[lang].dbpedia_sparql_url,
                                data: {
                                    query: otherSparqlTpl({ wikipedia_url: wk_url }),
                                    format: "application/sparql-results+json"
                                },
                                dataType: "json",
                                success: function(data) {
                                    if (data.results.bindings.length) {
                                        //console.log("Data found in "+lang+" DbPedia", data.results.bindings[0]);
                                        onBindingsLoaded(data, { dbpedia_language: lang });
                                    } else {
                                        //console.log("Data not found in "+lang+" DbPedia");
                                        onError();
                                    }
                                },
                                error: onError
                            });
                        } else {
                            //console.log("Data not found in french DbPedia and there is no known endpoint for "+lang);
                            onError();
                        }
                    }
                },
                error: onError
            });
        }
    }
    
    var $curitem = null,
        $overlay = $(".dbpedia-overlay"),
        $overlayImg = $overlay.find("img"),
        $h2 = $overlay.find("h2"),
        $abstract = $overlay.find(".dbpedia-abstract"),
        $source = $overlay.find(".dbpedia-source a"),
        hovering = false;
    
    $overlay.hover(function() {
        hovering = true;
    }, function() {
        hovering = false;
        hideOverlay();
    });
    
    function hideOverlay() {
        if (!$curitem && !hovering) {
            $overlayImg.attr("src","");
            $overlay.hide();
        }
    }
    
    function showOverlay(label, termdata) {
        if (!$curitem) {
            return;
        }
        var o = $curitem.offset();
        $overlay.css({
            top: o.top + $curitem.outerHeight(true),
            left: o.left - $overlay.outerWidth(true),
        }).show().attr("data-dbpedia-uri", termdata.dbpedia_uri);
        if (termdata.local.thumbnail) {
            $overlayImg.attr("src",termdata.local.thumbnail).show();
        } else {
            $overlayImg.hide();
        }
        $h2.text(termdata.label);
        if (label !== termdata.label) {
            $h2.prepend($('<span style="font-style: italic;">').text(label  + " → "));
        }
        $abstract.text((termdata.local.abstract || "").replace(/^(.{240,260})\s.+$/,'$1…').substr(0,261));
        $source.attr("href", termdata.wikipedia_url);
    }
    
    var tmpTemplate = '<li class="notice-term term-translated"></li>',
        $ntl = $(".notice-contribution-list");
    
    $(".notice-contribution-field").autocomplete({
        source: function( request, response ) {
            if (labelsCache[request.term]) {
                response(labelsCache[request.term]);
            }
            if (typeof labelsCache[request.term] === "undefined") {
                labelsCache[request.term] = false;
                $.ajax({
                   url : "http://" + lang + ".wikipedia.org/w/api.php",
                   dataType: "jsonp",
                   data : {
                       action: "opensearch",
                       search: request.term,
                       format: "json",
                       limit: 10
                   },
                   success: function( data ) {
                       labelsCache[request.term] = _.map( data[1], function(item) {
                           return {
                               label: item,
                               value: item
                           };
                       });
                       response(labelsCache[request.term]);
                   }
                });
            }
        },
        focus: function(e, ui) {
            $curitem = $(this);
            hovering = false;
            $overlay.hide();
            getDbpedia(ui.item.label, showOverlay);
        },
        select: function(e, ui) {
            var $this = $(this),
                $tmpItem = $(tmpTemplate);
            $ntl.append($tmpItem);
            $tmpItem.text(gettext("Validating Resource…"));
            $this.autocomplete("close");
            $this.val("");
            getDbpedia(ui.item.label, function(label, termdata) {
                $tmpItem.text(gettext("Saving contribution…"));
                if (termdata.dbpedia_uri) {
                    $.ajax({
                        url: urls.ajax_contribute,
                        dataType: "html",
                        type: "POST",
                        data: {
                            csrfmiddlewaretoken: csrf_token,
                            notice_id: notice_id,
                            dbpedia_language: termdata.dbpedia_language,
                            dbpedia_uri: termdata.dbpedia_uri,
                            translations: JSON.stringify(termdata.translations),
                            thesaurus_label: $this.attr("data-thesaurus-label")
                        },
                        success: function(html) {
                            var $el = $(html),
                                samecontrib = $ntl.find("[data-contribution-id='" + $el.attr("data-contribution-id") + "']");
                            if (samecontrib.length) {
                                samecontrib.replaceWith($el);
                            } else {
                                $ntl.append($el);
                            }
                            $tmpItem.remove();
                            dbpediaBox.bind($el);
                        },
                        error: function() {
                            $tmpItem.remove();
                        }
                    });
                } else {
                    $tmpItem.remove();
                    alert(gettext("No DbPedia resource found for term") + " " + ui.item.label);
                }
            }, function() {
                $tmpItem.remove();
                alert(gettext("No DbPedia resource found for term") + " " + ui.item.label);
            });
        },
        close: function(e, ui) {
            $curitem = null;
            hideOverlay();
        },
        minLength: 2
    });
    
    $(".notice-contribution-list").on("click",".contribution-upvote, .contribution-downvote", function() {
        var $this = $(this),
            $li = $(this).parents("li"),
            $list = $li.parent(),
            endpoint = urls[$this.hasClass("contribution-upvote") ? "upvote" : "downvote"];
        $.ajax({
            url: endpoint,
            dataType: "html",
            type: "POST",
            data: {
                csrfmiddlewaretoken: csrf_token,
                contribution_id: $li.attr("data-contribution-id"),
            },
            success: function(html) {
                if ($list.hasClass("contribution-novote")) {
                    $li.hide();
                } else {
                    $li.replaceWith($(html));
                }
                
            }
        });
        return false;
    });
});
