$(function() {
    var startYear = -500,
        endYear = 2012,
        zoomLevel = 1,
        zoomStep = Math.SQRT2,
        minZoomLevel = .5,
        maxZoomLevel = 128,
        baseSpan = (endYear - startYear),
        $tlcontainer = $(".timeline-container"),
        canvas = $tlcontainer.find('canvas')[0],
        lineDistances = [ 1000, 500, 200, 100, 50, 25, 10, 5, 2, 1 ],
        cWidth, cHeight,
        wSpan, wStart, wEnd, wScale, wLineDist,
        wCenter = baseSpan / 2 + startYear,
        itemCount = 12,
        tlCache = [], tlIdCache = [], currentTerm = null;
    
    function updateCoords() {
        cWidth = $tlcontainer.width();
        cHeight = $tlcontainer.height();
        wSpan = baseSpan / zoomLevel;
        wStart = wCenter - wSpan / 2;
        wEnd = wCenter + wSpan / 2;
        wScale = cWidth / wSpan;
        wLineDist = null;
        for (var i = 0; i < lineDistances.length; i++) {
            if (lineDistances[i] * wScale < 50) {
                break;
            }
            wLineDist = lineDistances[i];
        }
    }
    
    function yrToX(yr) {
        return wScale * (yr - wStart);
    }
    
    function xToYr(x) {
        return wStart + x / wScale;
    }
    
    var itemTpl = _.template(
        '<li class="timeline-item"><div class="timeline-item-box<%- current ? " timeline-current" : "" %>"'
        + ' data-dbpedia-uri="<%- item.dbpedia_uri %>" style="left: <%- left %>px; width: <%- width %>px;">'
        + '<div class="timeline-item-label"><%- item.label %></div></div></li>'
    );
    
    function redrawView() {
        canvas.width = cWidth;
        canvas.height = cHeight;
        
        var ctx = canvas.getContext("2d");
        
        for (var y = wLineDist * Math.ceil(wStart/wLineDist); y <= wEnd; y += wLineDist ) {
            var x = yrToX(y+1/2);
            ctx.beginPath();
            ctx.moveTo(x, 20);
            ctx.lineTo(x, cHeight - 20);
            ctx.stroke();
            ctx.textAlign = 'center';
            ctx.fillText(y || 1, x, 12);
            ctx.fillText(y || 1, x, cHeight - 8);
        }
        var html = _(tlCache).chain()
            .filter(function(item) {
                return (item.end_year >= wStart && item.start_year <= wEnd);
            }).first(itemCount)
            .sortBy(function(item) {
                return (item.start_year + item.end_year)
            }).map(function(item) {
                var l = Math.max(0, yrToX(item.start_year)),
                    r = Math.min(cWidth, yrToX(item.end_year + 1));
                return itemTpl({
                    current: (item.dbpedia_uri == currentTerm),
                    item: item,
                    left: l,
                    width: (r-l)
                });
            }).value().join("");
        $(".timeline-list").html(html);
        bindDbpediaBox(".timeline-item-box");
        $(".timeline-item-box").click(function() {
            var $this = $(this);
            currentTerm = $this.attr("data-dbpedia-uri")
            $(".timeline-item-box").removeClass("timeline-current");
            $this.addClass("timeline-current");
            $(".results").empty().load(
                urls.ajax_contents + "?random=1&dbpedia_uri=" + encodeURIComponent(currentTerm)
            );
        })
    }
    
    function getData() {
        $.getJSON(
            urls.ajax_years,
            {
                from_year: Math.floor(wStart),
                to_year: Math.floor(wEnd)
            },
            function(data) {
                _(data).each(function(term) {
                    if (tlIdCache.indexOf(term.dbpedia_uri) === -1) {
                        tlIdCache.push(term.dbpedia_uri);
                        tlCache.push(term);
                    }
                });
                tlCache = _(tlCache).sortBy(function(item) {
                    return -item.nb_notice;
                });
                throttledRedraw();
            }
        );
    }
    
    var throttledRedraw = _.throttle(function() {
        updateCoords();
        redrawView();
    }, 100);
    
    var debouncedGetData = _.debounce(getData, 1000);
        
    var mousedown = false, dragging = false, xstart = null, wcStart;
    
    throttledRedraw();
    
    $tlcontainer.mousedown(function(e) {
        dragging = false;
        mousedown = true;
        xstart = e.clientX;
        wcStart = wCenter;
        return false;
    }).mousemove(function(e) {
        if (mousedown) {
            dragging = true;
            wCenter = Math.max(startYear, Math.min(endYear, wcStart + (xstart - e.clientX) / wScale ));
            throttledRedraw();
            debouncedGetData();
            return false;
        }
    }).mousewheel(function(e, d) {
        var yrMouse = xToYr(e.clientX - $(this).offset().left),
            scaleRatio = (d > 0 ? zoomStep : 1/zoomStep);
        if (d < 0 && zoomLevel <= minZoomLevel) {
            return;
        }
        if (d >= 0 && zoomLevel >= maxZoomLevel) {
            return;
        }
        zoomLevel *= scaleRatio;
        console.log(zoomLevel);
        wCenter = Math.max(startYear, Math.min(endYear, yrMouse * (1 - 1 / scaleRatio) + wCenter / scaleRatio ));
        throttledRedraw();
        debouncedGetData();
    });
    
    $("body").mouseup(function() {
        mousedown = false;
        dragging = false;
    });
    
    getData();
    
    $(window).resize(throttledRedraw);
    
});
