/**
 * Handles aspects of the Calendar's UI, such as the vertical positioning of
 * release elements within the calendar & the adjustment of the heigh of each
 * calendar day based on the tallest day. Also ensures that the Next and Back
 * buttons on the calendar are handled via AJAX.
 *
 * @namespace WORKAREA.calendars
 */
WORKAREA.registerModule('calendars', (function () {
    'use strict';

    var countReleases = function (container) {
            return $('.calendar__release', container).length;
        },

        daysWithReleases = function (calendar) {
            return $('td', calendar).has('.calendar__release');
        },

        compensatePosition = function (top, release) {
            return top - $(release).position().top;
        },

        getReleaseOnPrevDay = function (releaseId, $prev) {
            var $releases = $('[data-calendar-release-id]', $prev);

            return $releases.filter(function (index, release) {
                return $(release).data('calendarReleaseId') === releaseId;
            });
        },

        resetCalendar = function (event) {
            var calendar = event.delegateTarget,
                today = new Date(),
                endpoint = WORKAREA.routes.admin.releasesPath();

            event.preventDefault();

            WORKAREA.releaseCalendarPlaceholders.requestCalendar(
                today, calendar, endpoint
            );
        },

        requestNewCalendar = function (event) {
            var calendar = event.delegateTarget,
                parsedHref = WORKAREA.url.parse(event.currentTarget.href),
                startDate = parsedHref.queryKey.start_date,
                endpoint = parsedHref.path;

            event.preventDefault();

            WORKAREA.releaseCalendarPlaceholders.requestCalendar(
                startDate, calendar, endpoint
            );
        },

        showTodayButton = function (calendar) {
            var $todayButton = $('.calendar__today-button', calendar);

            if (_.isEmpty($('.calendar__day--today', calendar))) {
                $todayButton.addClass('calendar__today-button--active');
            } else {
                $todayButton.removeClass('calendar__today-button--active');
            }
        },

        adjustHeightOfCell = function (top, release) {

            var topInteger = parseInt(top);

            if (topInteger > 0) {
                var currentHeight = $(release).closest('.calendar__day').css('height'),
                    newHeight = parseInt(currentHeight) + topInteger;

                $(release).closest('.calendar__day').css({height: newHeight + 'px'});
            }
        },

        adjustRelease = function ($prev, index, release) {
            var releaseId = $(release).data('calendarReleaseId'),
                $prevRelease = getReleaseOnPrevDay(releaseId, $prev),
                top,
                $prevReleaseOnDay = $(release).prev('.calendar__release');

            if (_.isEmpty($prevRelease)) {
                top =  $prevReleaseOnDay.css('top');
                adjustHeightOfCell(top, release);
            } else {
                top = compensatePosition($prevRelease.position().top, release);
                top = top || $prevRelease.css('marginTop');
            }

            $(release).css({ position: 'relative', top: top });
        },

        findReleasesToAdjust = function (index, day) {
            var $day = $(day),
                $prev = $(day).prev(),
                releasesOnDay = countReleases($day);

            $(day).data('releasesOnDay', {
                $day: $day,
                releaseCount: releasesOnDay
            });

            $('.calendar__release', $day).each(_.partial(adjustRelease, $prev));
        },

        initCalendar = function (index, calendar) {
            daysWithReleases(calendar).each(findReleasesToAdjust);
            showTodayButton(calendar);
        },

        /**
         * @method
         * @name init
         * @memberof WORKAREA.calendars
         */
        init = function ($scope) {
            $('.calendar', $scope)
                .addBack('.calendar')
                .on('click', '.calendar__control', requestNewCalendar)
                .on('click', '[data-calendar-today-button]', resetCalendar)
                .each(initCalendar);
        };

    return {
        init: init
    };
}()));