/**
 * Navigation tabs control
 *
 * Every nav tab content has an url conform ID (title, it comes from brick entries).
 * You can use it to target and auto open this element. Simply place `#open_` before your title in the url.
 * The page will be scrolled to the element if it is not in viewport.
 *
 * Example: <a href="www.example.com/subpage#open_myTarget">Open "myTarget" element</a>
 *
 * @module package/quiqqer/menu/bin/Controls/NavTabs
 * @author www.pcsg.de (Michael Danielczok)
 */
define('package/quiqqer/menu/bin/Controls/NavTabs', [

    'qui/QUI',
    'qui/controls/Control'

], function (QUI, QUIControl) {
    "use strict";

    return new Class({

        Extends: QUIControl,
        Type   : 'package/quiqqer/menu/bin/Controls/NavTabs',

        Binds: [
            '$onImport',
            'toggle'
        ],

        options: {
            animation: 'slide'
        },

        initialize: function (options) {
            this.parent(options);

            this.navTab              = false;
            this.navTabsItems        = false;
            this.navContents         = false;
            this.NavContentContainer = null;
            this.ActiveNavTab        = null;
            this.ActiveContent       = null;
            this.clicked             = false;
            this.animation           = 'slide';

            this.addEvents({
                onImport: this.$onImport
            });
        },

        $onImport: function () {
            var Elm  = this.getElm(),
                self = this;

            this.navTab              = Elm.getElement('.quiqqer-tab-nav');
            this.navTabsItems        = Elm.getElements('.quiqqer-tab-nav-item');
            this.navContents         = Elm.getElements('.quiqqer-tab-content-item');
            this.NavContentContainer = Elm.getElement('.quiqqer-tab-content');

            if (!this.navTabsItems || !this.navContents) {
                return;
            }

            // animation effect
            if (this.getAttribute('animation')) {
                switch (this.getAttribute('animation')) {
                    case 'slide':
                    default:
                        this.animation = 'slide';
                }
            }

            this.ActiveNavTab  = Elm.getElement('.quiqqer-tab-nav-item.active');
            this.ActiveContent = Elm.getElement('.quiqqer-tab-content-item.active');

            let queryString = window.location.hash;

            if (queryString && queryString.substr(0, 6) === '#open_') {
                const target     = decodeURI(queryString.substr(6));
                const NavTabItem = this.navTab.querySelector('[href="#' + target + '"]');

                if (NavTabItem) {
                    if (!this.$isInViewport(Elm)) {
                        new Fx.Scroll(window, {
                            duration: 500
                        }).toElement(Elm);
                    }

                    self.$setNavItemPos(NavTabItem.parentElement);
                    self.toggle(NavTabItem.parentElement, target);
                }
            }

            let clickEvent = function (event) {
                event.stop();

                if (self.clicked) {
                    return;
                }

                self.clicked = true;

                let NavTabItem = event.target;

                if (NavTabItem.nodeName !== 'LI') {
                    NavTabItem = NavTabItem.getParent('li');
                }

                let target = NavTabItem.getElement('a').getAttribute("href");

                if (target.indexOf('#') === 0) {
                    target = target.substring(1)
                }

                if (!target) {
                    self.clicked = false;
                    return;
                }

                self.$setNavItemPos(NavTabItem);
                self.toggle(NavTabItem, target);
            }

            this.navTabsItems.addEvent('click', clickEvent);
        },

        /**
         * Toggle nav tabs
         *
         * @param NavItem HTMLNode
         * @param target string
         */
        toggle: function (NavItem, target) {
            if (NavItem.hasClass('active')) {
                this.clicked = false;
                return;
            }

            var TabContent = this.getElm().getElement('[id="' + target + '"]');

            if (!TabContent) {
                this.clicked = false;
                return;
            }

            var self = this;

            Promise.all([
                this.disableNavItem(this.ActiveNavTab),
                this.hideContent(this.ActiveContent)
            ]).then(function () {
                TabContent.setStyle('display', null);

                return Promise.all([
                    self.enableNavItem(NavItem),
                    self.showContent(TabContent),
                    self.$setHeight(TabContent.offsetHeight)
                ]);
            }).then(function () {
                self.clicked = false;
                self.NavContentContainer.setStyle('height', null);
            });
        },

        /**
         * Set nav item to inactive
         *
         * @param Item HTMLNode
         * @return Promise
         */
        disableNavItem: function (Item) {
            return new Promise(function (resolve) {
                Item.removeClass('active');

                resolve();
            });
        },

        /**
         * Set nav item to active
         *
         * @param Item HTMLNode
         * @return Promise
         */
        enableNavItem: function (Item) {
            var self = this;

            return new Promise(function (resolve) {
                Item.addClass('active');
                self.ActiveNavTab = Item;

                resolve();
            });
        },

        /**
         * Hide tab content
         *
         * @param Item HTMLNode
         * @return Promise
         */
        hideContent: function (Item) {
            var self = this;

            return new Promise(function (resolve) {
                self.$slideFadeOut(Item).then(function () {
                    Item.removeClass('active');
                    Item.setStyle('display', 'none');

                    resolve();
                });
            });
        },

        /**
         * Show tab content
         *
         * @param Item HTMLNode
         * @return Promise
         */
        showContent: function (Item) {
            var self = this;

            return new Promise(function (resolve) {
                self.$slideFadeIn(Item).then(function () {
                    Item.addClass('active');
                    Item.setStyle('display', null);
                    self.ActiveContent = Item;

                    resolve();
                });
            });
        },

        /**
         * Set heigt of tab content container
         *
         * @param height integer
         * @return Promise
         */
        $setHeight: function (height) {
            var self = this;

            return new Promise(function (resolve) {
                moofx(self.NavContentContainer).animate({
                    height: height
                }, {
                    duration: 250,
                    callback: resolve
                });
            });
        },

        /**
         * Fade out animation (hide)
         *
         * @param Item HTMLNode
         * @return Promise
         */
        $slideFadeOut: function (Item) {
            this.NavContentContainer.setStyle('height', Item.offsetHeight)

            return new Promise(function (resolve) {
                moofx(Item).animate({
                    transform: 'translateX(-10px)',
                    opacity  : 0
                }, {
                    duration: 250,
                    callback: resolve
                });
            });
        },

        /**
         * Fade in animation (show)
         *
         * @param Item HTMLNode
         * @return Promise
         */
        $slideFadeIn: function (Item) {
            Item.setStyles({
                transform: 'translateX(-10px)',
                opacity  : 0
            });

            return new Promise(function (resolve) {
                moofx(Item).animate({
                    transform: 'translateX(0)',
                    opacity  : 1
                }, {
                    duration: 250,
                    callback: resolve
                });
            });
        },

        /**
         * Scroll active nav item to the left edge (on mobile)
         *
         * @param Item
         */
        $setNavItemPos: function (Item) {
            if (!Item) {
                return;
            }

            if (QUI.getWindowSize().x > 767) {
                return;
            }

            let paddingLeft = window.getComputedStyle(this.navTab, null).getPropertyValue('padding-left'),
                marginLeft  = window.getComputedStyle(Item, null).getPropertyValue('padding-left');

            new Fx.Scroll(this.navTab).start(Item.offsetLeft - parseInt(paddingLeft) - parseInt(marginLeft), 0);
        },

        /**
         * Check if element is in viewport
         * @param element
         * @return {boolean}
         */
        $isInViewport: function (element) {
            const rect = element.getBoundingClientRect();
            return (
                rect.top >= 0 &&
                rect.left >= 0 &&
                rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
                rect.right <= (window.innerWidth || document.documentElement.clientWidth)
            );
        }
    });
});