/* --------------------------------------------------------------
 datatable_fixed_header.js 2016-07-13
 Gambio GmbH
 http://www.gambio.de
 Copyright (c) 2016 Gambio GmbH
 Released under the GNU General Public License (Version 2)
 [http://www.gnu.org/licenses/gpl-2.0.html]
 --------------------------------------------------------------
 */

/**
 * ## Enable Fixed DataTable Header
 *
 * The table header will remain in the viewport as the user scrolls down the page. The style change of this
 * module is a bit tricky because we need to remove the thead from the normal flow, something that breaks the
 * display of the table. Therefore a helper clone of the thead is used to maintain the table formatting.
 *
 * **Notice #1**: The .table-fixed-header class is styled by the _tables.scss and is part of this solution.
 *
 * **Notice #2**: This method will take into concern the .content-header element which shouldn't overlap the
 * table header.
 *
 * @module Admin/Extensions/datatable_fixed_header
 */
gx.extensions.module('datatable_fixed_header', [], function (data) {

    'use strict';

    // ------------------------------------------------------------------------
    // VARIABLES
    // ------------------------------------------------------------------------

    /**
     * Module Selector
     *
     * @type {jQuery}
     */
    const $this = $(this);

    /**
     * Table Header Selector
     *
     * @type {jQuery}
     */
    const $thead = $this.children('thead');

    /**
     * Module Instance
     *
     * @type {Object}
     */
    const module = {};

    /**
     * Marks the end of the table.
     *
     * This value is used to stop the fixed header when the user reaches the end of the table.
     *
     * @type {Number}
     */
    let tableOffsetBottom;

    // ------------------------------------------------------------------------
    // FUNCTIONS
    // ------------------------------------------------------------------------

    /**
     * On DataTable Draw Event
     *
     * Re-calculate the table bottom offset value.
     */
    function _onDataTableDraw() {
        tableOffsetBottom = $this.offset().top + $this.height() - $thead.height();
    }

    /**
     * On DataTable Initialization
     *
     * Modify the table HTML and set the required event handling for the fixed header functionality.
     */
    function _onDataTableInit() {
        const $mainHeader = $('#main-header');
        const $contentHeader = $('.content-header');
        const $clone = $thead.clone();
        const originalTop = $thead.offset().top;
        let isFixed = false;
        let rollingAnimationInterval = null;

        $clone
            .hide()
            .addClass('table-fixed-header-helper')
            .prependTo($this);

        $(window)
            .on('scroll', function () {
                const scrollTop = $(window).scrollTop();

                if (!isFixed && scrollTop + $mainHeader.outerHeight() > originalTop) {
                    $this.addClass('table-fixed-header');
                    $thead
                        .outerWidth($this.outerWidth())
                        .addClass('fixed');
                    $clone.show();
                    isFixed = true;
                } else if (isFixed && scrollTop + $mainHeader.outerHeight() < originalTop) {
                    $this.removeClass('table-fixed-header');
                    $thead
                        .outerWidth('')
                        .removeClass('fixed');
                    $clone.hide();
                    isFixed = false;
                }

                if (scrollTop >= tableOffsetBottom) {
                    $thead.removeClass('fixed');
                } else if ($(window).scrollTop() < tableOffsetBottom && !$thead.hasClass('fixed')) {
                    $thead.addClass('fixed');
                }
            })
            .on('content_header:roll_in', function () {
                rollingAnimationInterval = setInterval(() => {
                    $thead.css('top', $contentHeader.position().top + $contentHeader.outerHeight());
                    if ($contentHeader.hasClass('fixed')) {
                        clearInterval(rollingAnimationInterval);
                    }
                }, 1);
            })
            .on('content_header:roll_out', function () {
                clearInterval(rollingAnimationInterval);
                $thead.css('top', $mainHeader.outerHeight());
            });
    }


    // ------------------------------------------------------------------------
    // INITIALIZATION
    // ------------------------------------------------------------------------

    module.init = function (done) {
        $(window).on('JSENGINE_INIT_FINISHED', () => {
            $this
                .on('draw.dt', _onDataTableDraw)
                .on('init.dt', _onDataTableInit);

            // Setup fixed header functionality if the table is already initialized.
            if ($this.DataTable().ajax.json() !== undefined) {
                _onDataTableInit();
            }
        });

        done();
    };

    return module;

});