/* jslint white, browser, nomen, strict, maxlen: 100 */
/*global alert, confirm, jQuery, LANGUAGE_CODE, gettext, WDL, _gaq */
jQuery(function ($) {
    "use strict";
    var regions;
    var time_periods = [],
        current_start_year = -8000, current_end_year = new Date().getFullYear(),
        /* Since our slider scale isn't linear we will use some constants to
           map absolute slider position to the labels */
        SLIDER_YEARS = [-8000, -8000, -4250, -499, 500, 1000, 1499, 1500, 1600,
                        1699, 1700, 1750, 1799, 1800, 1825, 1849, 1850, 1875,
                        1899, 1900, 1925, 1949, 1950, 2000,
                        current_end_year],
        SLIDER_VALUE_SCALE = [0, 2, 6, 9, 13, 18, 23, 25, 31, 35, 38, 45, 49,
                              51, 58, 62, 65, 71, 75, 78, 85, 89, 91, 96, 100];

    var $map = $("#map"),
        $timeline = $("#timeselector");

    /* We'll add a span which will hold the counts for each region's view */
    $map.find(".region .browse").prepend('<span class="count"></span>&nbsp;');

    function unique(input_array) {
        var tmp = {}, out = [];

        for (var i = input_array.length - 1; i >= 0; i--){
            tmp[input_array[i]] = 1;
        }

        for (var k in tmp) {
            if (tmp.hasOwnProperty(k)) {
                out.push(k);
            }
        }

        return out;
    }

    function update_map() {
        var region_totals = {},
            all_items = [],
            grand_total = 0;

        // Clear the data for all regions:
        $(".region").data("item-count", 0);

        $.each(regions, function (idx, region) {
            if (region_totals[region.slug] === undefined) {
                region_totals[region.slug] = [];
            }
            $.each(region.region_items, function(c, item) {
                if (item.s > current_end_year || item.e < current_start_year){
                    return;
                }
                region_totals[region.slug].push(item.id);
            });
        });

        $.each(region_totals, function (slug, region_items) {
            var region_count = unique(region_items).length;
            $map.find("#" + slug).data("item-count", region_count);
            $.merge(all_items, region_items);
        });

        $(".region").each(function() {
            var $region = $(this),
                count = $region.data("item-count");

            $region.find(".count").text(WDL.translateNumber(count));

            if (count > 0) {
                $region.fadeIn();
            } else {
                $region.fadeOut();
            }
        });

        var item_count = unique(all_items).length;

        $timeline.find(".selection .count").text(WDL.translateNumber(item_count));
    }

    function mapValueToYear(val) {
        /* Given an absolute slider position in the range 0-100, return the
           appropriate year to display

           The indexes in SLIDER_VALUE_SCALE and SLIDER_YEARS must correspond so
           we can find the SLIDER_VALUE_SCALE elements which bound
           the current slider value and use its index to retrieve the
           corresponding SLIDER_YEARS high and low values. These are then used
           to calculate the year to display by scaling the high and low year values
           correspondingly to the high and low slider positions
        */

        for (var i = 0; i < SLIDER_VALUE_SCALE.length - 1; i++) {
            var low_pos = SLIDER_VALUE_SCALE[i],
                high_pos = SLIDER_VALUE_SCALE[i + 1],
                low_year = SLIDER_YEARS[i],
                high_year = SLIDER_YEARS[i + 1];

            if (low_pos <= val && val <= high_pos) {
                return Math.floor(low_year + ((val - low_pos) * (low_year - high_year)) / (low_pos - high_pos));
            }
        }
    }

    $.get('/' + LANGUAGE_CODE + '/api/v1/region/', function (data) {
        regions = data;

        var $after_label = $("#after"),
            $after_era = $("#after_era_label"),
            $before_label = $("#before"),
            $before_era = $("#before_era_label");

        /* Now that we have the actual time periods data we can initialize the slider */
        $timeline.find(".slider").show().slider({
            range: true,
            min: 0,
            max: 100,
            values: [0, 100],
            slide: function(event, ui) {
                if (LANGUAGE_CODE != "ar") {
                    current_start_year = mapValueToYear(ui.values[0]);
                    current_end_year = mapValueToYear(ui.values[1]);
                } else {
                    current_start_year = mapValueToYear(100 - ui.values[1]);
                    current_end_year = mapValueToYear(100 - ui.values[0]);
                }

                $after_label.text(WDL.translateNumber(Math.abs(current_start_year)));
                $after_era.text(current_start_year < 0 ? gettext("BCE") : gettext("CE"));
                $before_label.text(WDL.translateNumber(Math.abs(current_end_year)));
                $before_era.text(current_end_year < 0 ? gettext("BCE") : gettext("CE"));

                $("#map a.browse").add("#timeselector .items a").each(function () {
                    var href = this.href, qs;

                    if (href.indexOf("?") === -1) {
                        href += "?"; // Avoid jQuery BBQ bug parsing URLs w/o querystrings
                    }

                    qs = $.deparam.querystring(href);

                    qs.start_year = current_start_year;
                    qs.end_year = current_end_year;

                    this.href = $.param.querystring(this.href, qs);
                });

                update_map();

                if (ui.value == ui.values[0]) {
                    _gaq.push(['_trackEvent', 'Timeline', 'Start Year', current_start_year]);
                } else {
                    _gaq.push(['_trackEvent', 'Timeline', 'End Year', current_end_year]);
                }
            }
        });

        $timeline.find(".ui-slider-handle")
            .eq(0).addClass('start')
            .end()
            .eq(1).addClass('end');

        update_map();
    });
});

$("#map").delegate(".region:not(.selected-region) .thumbnail", "click", function(e) {
    e.preventDefault();

    var $region = $(this).parents(".region"),
        $titlebar = $region.children("h3"),
        $href = $region.children("a").attr('href'),
        $title = $region.find(".title"),
        $thumbnail = $region.find(".thumbnail img"),
        $map = $("#map"),
        $tray = $("<div>").addClass("tray").appendTo($region),
        region_id = $region.attr("id"),
        ajax_url = "/"+ $("html").attr("lang") + "/api/v1/item/",
        page_size = 6,
        current_start_year = -8000,
        current_end_year = new Date().getFullYear();

        qs = $.deparam.querystring($href);
        if (qs.start_year){
           current_start_year = qs.start_year;
        };
        if (qs.end_year){
           current_end_year = qs.end_year;
        };

    $("<li>").addClass("overlay").appendTo($("#map .region-wrapper"));

    $region
        .data('original-dimensions',
              $.extend($region.position(), {height: $region.height(),
                                            width: $region.width()}))
        .css("z-index", 1400)
        .animate({left: '268px', top: '118px',
                  width: '415px', height: '180px'},
                  {duration: 750,
                   easing: "linear",
                   complete: function () {
                       $region.addClass("selected-region");
                       $title.fadeIn("fast").addClass("expanded");
                   }});

    var $page_previous = $("<div>").addClass("page previous disabled").appendTo($tray),
        $contents = $("<div>").addClass("contents").appendTo($tray),
        $page_next = $("<div>").addClass("page next").appendTo($tray);

    $thumbnail
        .data({"original-src": $thumbnail.attr("src"),
               "original-href": $thumbnail.parent().attr("href")})
        .attr({height: 83, width: 100,
               src: $thumbnail.attr("src").replace("64x53", "100x83")});

    var $item_list = $("<ul>").addClass("items").appendTo($contents)
        .delegate("img", "click", function() {
            var $this = $(this),
                data = $this.data();

            if (!data.title || !data.uri) {
                $region.find(".title a").text("");
                return;
            }

            $region.find(".title a").attr("href", data.uri).text(data.title);

            $thumbnail
                .attr("src", MEDIA_URL + data.wdl_id + "/thumbnail/100x83.jpg")
                .parent().attr("href", data.uri);
        });

    $("<div>").addClass("slider-container").appendTo($contents);

    //Window close button
    $("<span>").addClass("close").appendTo($titlebar)
        .click(function() {

        $map.find(".overlay").remove();

        $region.find(".tray").add(".close").remove();

        $region.find(".title").removeClass("expanded").hide();

        $thumbnail.attr({height: 53, width: 64,
                         src: $thumbnail.data("original-src")})
                  .parent().attr("href", $thumbnail.data("original-href"));

        $region
            .removeClass("selected-region")
            .animate($region.data("original-dimensions"), "fast",
                        function () {
                            $region.css("z-index", "inherit");

                        });

        _gaq.push(['_trackEvent', 'Homepage', 'Close Cluster', $region.attr("id")]);
    });

    function update_images(data) {
        var slider_start = Math.min($(".slider").slider("value"), data.meta.total_count - page_size),
            slider_end = Math.max(0, slider_start + page_size);

        for (var i=0; i < data.objects.length; i++) {
            var img_pos = data.meta.offset + i,
                obj = data.objects[i],
                $img = $item_list.find("img").slice(img_pos).first();

            if (!$img) {
                continue;
            }

            // Store all of the retrieved data:
            $img
                .attr({'title': obj.title,
                       'data-thumbnail-src': obj.thumbnail_uri})
                .data({'title': obj.title,
                       'uri': obj.uri,
                       'wdl_id': obj.wdl_id});

            if (img_pos >= slider_start && img_pos <= slider_end) {
                $img.attr('src', obj.thumbnail_uri);
            }
        }
    }

    function load_tray(data) {
        var $placeholder = $('<li>'),
            $slider = $("<div>").addClass("slider");

        $("<img>")
            .attr({"src": MEDIA_URL + "placeholder/64x53.png", "height": 53, "width": 64})
            .appendTo($placeholder);

        $tray.show().data({
            "api-limit": data.meta.limit,
            "api-offset": data.meta.offset,
            "page-size": data.meta.limit,
            "total-item-count": data.meta.total_count
        });

        $(".slider-container")
            .empty()
            .append($slider);

        $slider.slider({value: 0, min: 0, max: data.meta.total_count, step: 1,
                        change: function (event, ui) {
                            // Check the pagination controls' enable/disable state:
                            $page_previous.toggleClass("disabled", ui.value == 0);
                            $page_next.toggleClass("disabled", ui.value >= data.meta.total_count - page_size);

                            // Ensure that the first item is visible in the slider:
                            $item_list.css("margin-left", -1 * Math.min(ui.value, data.meta.total_count - page_size) * 64 + "px");

                            /*
                                Start loading thumbnails

                                To improve cache hit ratios we'll round our request down to the next lowest
                                page size and then request the previous, current, and next page's information
                                so our AJAX requests will cover three full pages and be evenly aligned.
                                update_images() can choose not to replace a placeholder image if it's not
                                visible by the time the response loads.
                             */
                             var visible_start, visible_end, /* the images which are actually visible*/
                                 start_slice, end_slice; /* the images which will be AJAX loaded if necessary */

                            visible_start = Math.min(ui.value, data.meta.total_count - page_size);
                            start_slice = Math.max(0, page_size * (Math.floor(visible_start / page_size) - 1));

                            visible_end = Math.min($tray.data("total-item-count"), visible_start + page_size);
                            end_slice = start_slice + (page_size * 3);

                            var $placeholders = $item_list.find("img").slice(start_slice, end_slice).filter("img[src*=placeholder]");

                            $placeholders.filter('[data-thumbnail-src]').each(function (i, e) {
                                var $e = $(e);
                                $e.attr("src", $(e).attr("data-thumbnail-src"));
                            });

                            var $visible_placeholders = $item_list.find("img")
                                                                    .slice(visible_start, visible_end)
                                                                    .filter("img[src*=placeholder]").filter(function (i, e) {
                                                                        return e.src.indexOf("placeholder") > -1;
                                                                    });

                            if ($visible_placeholders.length < 1) return;

                            WDL.ajaxRetry({url: ajax_url,
                                           data: {regions: region_id,
                                                  limit: page_size * 3,
                                                  start_year: current_start_year,
                                                  end_year: current_end_year,
                                                  offset: start_slice},
                                           timeout: 10000,
                                           success: update_images});

                           _gaq.push(['_trackEvent', 'Homepage', 'Tray Scroll', start_slice.toString()]);
                        }
            });

        // Note page values determined by the display size of our slider and
        // our thumbnail size:
        $page_next.click(function () {
            if (!($(this).hasClass("disabled"))) {
                $slider.slider("value", Math.min($slider.slider("value") + page_size, data.meta.total_count));
                _gaq.push(['_trackEvent', 'Homepage', 'Tray Next']);
            }
        });

        $page_previous.click(function () {
            if (!($(this).hasClass("disabled"))) {
                $slider.slider("value", Math.max($slider.slider("value") - page_size, 0));
                _gaq.push(['_trackEvent', 'Homepage', 'Tray Previous']);
            }
        });

        for (var i = data.meta.total_count; i > 0; i--) {
            $placeholder.clone().appendTo($item_list);
        }

        update_images(data);
    }

    $region.queue(function (next) {
        WDL.ajaxRetry({
            url: ajax_url,
            data: {regions: region_id, limit: page_size * 3, offset: 0, start_year: current_start_year, end_year: current_end_year},
            success: function(data) {
                $region.queue(function (next) {
                    load_tray(data);
                    next();
                });
            }
        });
        next();
    });
    _gaq.push(['_trackEvent', 'Homepage', 'Expand Cluster', region_id]);
});

