/**
 *  Component for TabBar
 *
 * @author Ivan Marshalkin
 * @date 2019-05-30
 */

import * as React from 'react';
import {renderIcon} from '../../utils/renderIcon';

import * as styles from './tabBar.m.css';
import {joinClassNames} from '../../utils/joinClassNames';
import {Divider, DIVIDER_TYPE} from '../divider/Divider';
import {IconIntent} from '@unidata/icon';

export type TabItem<KEY_ENUM extends string = string> = {
    key: KEY_ENUM;
    tab: React.ReactNode;
    leftIcon?: React.ReactNode;
    rightIcon?: React.ReactNode;
    isDisabled?: boolean;
    'data-qaid'?: string;
    order?: number;
    hasError?: boolean;
}

interface IProps <KEY_ENUM extends string = string> {
    defaultSelectedTab: KEY_ENUM;
    shouldTabChange?: (key: KEY_ENUM) => boolean;
    onTabSelect: (key: KEY_ENUM) => void;
    tabs: Array<TabItem<KEY_ENUM>> | Array<Array<TabItem<KEY_ENUM>>>;
    rightTabs?: Array<TabItem<KEY_ENUM>>;
}

interface IState<KEY_ENUM extends string = string> {
    selectedTab: KEY_ENUM;
}

export class TabBar<KEY_ENUM extends string = string> extends React.Component<IProps<KEY_ENUM>, IState<KEY_ENUM>> {

    override state: IState<KEY_ENUM> = {
        selectedTab: this.props.defaultSelectedTab
    };

    setTab = (key: KEY_ENUM) => () => {
        if (!this.props.shouldTabChange || this.props.shouldTabChange(key)) {
            this.setState({selectedTab: key});

            this.props.onTabSelect(key);
        }
    };

    override componentDidUpdate (prevProps: Readonly<IProps>, prevState: Readonly<IState>, snapshot?: any): void {
        if (prevProps.defaultSelectedTab !== this.props.defaultSelectedTab) {
            this.setState({selectedTab: this.props.defaultSelectedTab});
        }
    }

    renderTabItem = (tabMeta: TabItem<KEY_ENUM>) => {
        const tabItemClass = joinClassNames(
            styles.tabItem,
            [styles.tabSelected, tabMeta.key === this.state.selectedTab],
            [styles.isDisabled, Boolean(tabMeta.isDisabled)]
        );

        return (
            <div
                key={tabMeta.key}
                onClick={tabMeta.isDisabled !== true ? this.setTab(tabMeta.key) : undefined}
                className={tabItemClass}
            >
                {tabMeta.leftIcon && renderIcon(tabMeta.leftIcon, {
                    intent: tabMeta.key === this.state.selectedTab ? IconIntent.PRIMARY : IconIntent.DEFAULT
                }, {
                    className: styles.leftIcon
                })}
                {tabMeta.tab}
                {tabMeta.rightIcon && renderIcon(tabMeta.rightIcon, {
                    intent: tabMeta.key === this.state.selectedTab ? IconIntent.PRIMARY : IconIntent.DEFAULT
                }, {
                    className: styles.rightIcon
                })}
                {this.state.selectedTab === tabMeta.key && (
                    <div className={styles.selectedLine}/>
                )}

                {tabMeta.hasError === true && (<div className={styles.hasError}/>)}
            </div>
        );
    };

    override render () {
        const tabs = this.props.tabs;

        let showDivider = true;

        if (Array.isArray(tabs[0]) && Array.isArray(tabs[1]) && (tabs[0].length === 0 || tabs[1].length === 0)) {
            showDivider = false;
        }

        return (
            <div
                className={styles.tabBar}
                data-component-id={'TabBar'}
            >
                <div className={styles.tabGroup}>
                    {tabs.map((tabMeta, index) => {
                        if (Array.isArray(tabMeta)) {
                            const groupKey = tabMeta.map((tabMetaItem) => tabMetaItem.key).join();

                            return (
                                <React.Fragment key={groupKey}>
                                    {index > 0 && showDivider && (
                                        <Divider type={DIVIDER_TYPE.solid} orientation={'vertical'} offset={8} size={20}/>
                                    )}
                                    {tabMeta.map((tabItem) => this.renderTabItem(tabItem))}
                                </React.Fragment>
                            );
                        } else {
                            return this.renderTabItem(tabMeta);
                        }
                    })}
                </div>
                <div className={styles.tabGroup}>
                    {this.props.rightTabs?.map((tabMeta) => {
                        return this.renderTabItem(tabMeta);
                    })}
                </div>
            </div>
        );
    }
}
