"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = __importDefault(require("lodash"));
const NestedComponent_1 = __importDefault(require("../_classes/nested/NestedComponent"));
class TabsComponent extends NestedComponent_1.default {
    static schema(...extend) {
        return NestedComponent_1.default.schema({
            label: 'Tabs',
            type: 'tabs',
            input: false,
            key: 'tabs',
            persistent: false,
            tableView: false,
            components: [
                {
                    label: 'Tab 1',
                    key: 'tab1',
                    components: [],
                },
            ],
            verticalLayout: false,
        }, ...extend);
    }
    static get builderInfo() {
        return {
            title: 'Tabs',
            group: 'layout',
            icon: 'folder-o',
            weight: 50,
            documentation: '/userguide/form-building/layout-components#tabs',
            showPreview: false,
            schema: TabsComponent.schema(),
        };
    }
    static savedValueTypes() {
        return [];
    }
    get defaultSchema() {
        return TabsComponent.schema();
    }
    get schema() {
        const schema = super.schema;
        // We need to clone this because the builder uses the "components" reference and this would reset that reference.
        const components = lodash_1.default.cloneDeep(this.component.components);
        schema.components = components.map((tab, index) => {
            tab.components = this.tabs[index].map((component) => component.schema);
            return tab;
        });
        return schema;
    }
    get tabKey() {
        return `tab-${this.key}`;
    }
    get tabLikey() {
        return `tabLi-${this.key}`;
    }
    get tabLinkKey() {
        return `tabLink-${this.key}`;
    }
    constructor(...args) {
        super(...args);
        this.currentTab = 0;
        this.noField = true;
    }
    init() {
        this.components = [];
        this.tabs = [];
        lodash_1.default.each(this.component.components, (tab, index) => {
            this.tabs[index] = [];
            // Initialize empty tabs.
            tab.components = tab.components || [];
            lodash_1.default.each(tab.components, (comp) => {
                const component = this.createComponent(comp);
                component.tab = index;
                this.tabs[index].push(component);
            });
        });
    }
    render() {
        return super.render(this.renderTemplate('tab', {
            tabKey: this.tabKey,
            tabLikey: this.tabLikey,
            tabLinkKey: this.tabLinkKey,
            currentTab: this.currentTab,
            tabComponents: this.tabs.map((tab) => this.renderComponents(tab)),
        }, this.options.flatten || this.options.pdf ? 'flat' : null));
    }
    attach(element) {
        this.loadRefs(element, {
            [this.tabLinkKey]: 'multiple',
            [this.tabKey]: 'multiple',
            [this.tabLikey]: 'multiple',
        });
        [
            'change',
            'error',
        ].forEach((event) => this.on(event, this.handleTabsValidation.bind(this)));
        const superAttach = super.attach(element);
        this.refs[this.tabLinkKey].forEach((tabLink, index) => {
            this.addEventListener(tabLink, 'click', (event) => {
                event.preventDefault();
                this.setTab(index);
            });
        });
        this.refs[this.tabKey].forEach((tab, index) => {
            this.attachComponents(tab, this.tabs[index], this.component.components[index].components);
        });
        return superAttach;
    }
    detach(all) {
        super.detach(all);
    }
    /**
     * Set the current tab.
     * @param {number} index - The index of the tab to set.
     */
    setTab(index) {
        var _a;
        if (!this.tabs ||
            !this.tabs[index] ||
            !this.refs[this.tabKey] ||
            !this.refs[this.tabKey][index]) {
            return;
        }
        this.currentTab = index;
        lodash_1.default.each(this.refs[this.tabKey], (tab) => {
            this.removeClass(tab, 'formio-tab-panel-active');
            tab.style.display = 'none';
        });
        this.addClass(this.refs[this.tabKey][index], 'formio-tab-panel-active');
        this.refs[this.tabKey][index].style.display = 'block';
        lodash_1.default.each(this.refs[this.tabLinkKey], (tabLink, tabIndex) => {
            if (this.refs[this.tabLinkKey][tabIndex]) {
                this.removeClass(tabLink, 'active');
                this.removeClass(tabLink, 'formio-tab-link-active');
            }
            if (this.refs[this.tabLikey][tabIndex]) {
                this.removeClass(this.refs[this.tabLikey][tabIndex], 'active');
                this.removeClass(this.refs[this.tabLikey][tabIndex], 'formio-tab-link-container-active');
            }
        });
        if (this.refs[this.tabLikey][index]) {
            this.addClass(this.refs[this.tabLikey][index], 'active');
            this.addClass(this.refs[this.tabLikey][index], 'formio-tab-link-container-active');
        }
        if (this.refs[this.tabLinkKey][index]) {
            this.addClass(this.refs[this.tabLinkKey][index], 'active');
            this.addClass(this.refs[this.tabLinkKey][index], 'formio-tab-link-active');
        }
        this.setValue(this.data);
        (_a = this.triggerChange) === null || _a === void 0 ? void 0 : _a.call(this);
    }
    beforeFocus(component) {
        if ('beforeFocus' in this.parent) {
            this.parent.beforeFocus(this);
        }
        const tabIndex = this.tabs.findIndex((tab) => {
            return tab.some((comp) => comp === component);
        });
        if (tabIndex !== -1 && this.currentTab !== tabIndex) {
            this.setTab(tabIndex);
        }
    }
    setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {
        if (this.component.modalEdit) {
            super.setErrorClasses(elements, dirty, hasErrors, hasMessages, element);
        }
        elements.forEach((element) => {
            this.addClass(element, 'is-invalid');
            if (element.getAttribute('ref') !== 'openModal') {
                if (this.options.highlightErrors) {
                    this.addClass(element, 'tab-error');
                }
                else {
                    this.addClass(element, 'has-error');
                }
            }
        });
    }
    clearErrorClasses(elements) {
        if (this.options.server || !this.rendered) {
            return;
        }
        if (this.component.modalEdit) {
            const element = Array.isArray(elements) || elements instanceof NodeList ? this.element : elements;
            super.clearErrorClasses(element);
        }
        elements =
            Array.isArray(elements) || elements instanceof NodeList
                ? elements
                : [
                    elements,
                ];
        elements.forEach((element) => {
            this.removeClass(element, 'is-invalid');
            this.removeClass(element, 'tab-error');
            this.removeClass(element, 'has-error');
        });
    }
    handleTabsValidation() {
        if (!this.refs[this.tabLinkKey] || !this.refs[this.tabLinkKey].length || !this.tabs.length) {
            return;
        }
        this.clearErrorClasses(this.refs[this.tabLinkKey]);
        const invalidTabsIndexes = this.tabs.reduce((invalidTabs, tab, tabIndex) => {
            const hasComponentWithError = tab.some((comp) => !!comp.error);
            return hasComponentWithError
                ? [
                    ...invalidTabs,
                    tabIndex,
                ]
                : invalidTabs;
        }, []);
        if (!invalidTabsIndexes.length) {
            return;
        }
        const invalidTabs = [
            ...this.refs[this.tabLinkKey],
        ].filter((_, tabIndex) => invalidTabsIndexes.includes(tabIndex));
        this.setErrorClasses(invalidTabs);
    }
}
exports.default = TabsComponent;
