import * as React from "react";
import DockLocation from "../DockLocation";
import Border from "../model/BorderNode";
import TabNode from "../model/TabNode";
import { BorderButton } from "./BorderButton";
import { IIcons, ILayoutCallbacks } from "./Layout";
import { showPopup } from "../PopupMenu";
import Actions from "../model/Actions";
import { I18nLabel } from "../I18nLabel";
import { useTabOverflow } from "./TabOverflowHook";
import Orientation from "../Orientation";
import { CLASSES } from "../Types";
import { isAuxMouseEvent } from "./TabSet";

/** @hidden @internal */
export interface IBorderTabSetProps {
    border: Border;
    layout: ILayoutCallbacks;
    iconFactory?: (node: TabNode) => React.ReactNode | undefined;
    titleFactory?: (node: TabNode) => React.ReactNode | undefined;
    icons?: IIcons;
    path: string;
}

/** @hidden @internal */
export const BorderTabSet = (props: IBorderTabSetProps) => {
    const { border, layout, iconFactory, titleFactory, icons, path } = props;

    const toolbarRef = React.useRef<HTMLDivElement | null>(null);
    const overflowbuttonRef = React.useRef<HTMLButtonElement | null>(null);
    const stickyButtonsRef = React.useRef<HTMLDivElement | null>(null);

    const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel } = useTabOverflow(border, Orientation.flip(border.getOrientation()), toolbarRef, stickyButtonsRef);

    const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
        if (isAuxMouseEvent(event)) {
            layout.auxMouseClick(border, event);
        }
    };

    const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
        layout.showContextMenu(border, event);
    };

    const onInterceptMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.MouseEvent<HTMLButtonElement, MouseEvent> | React.TouchEvent<HTMLButtonElement>) => {
        event.stopPropagation();
    };

    const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
        const element = overflowbuttonRef.current!;
        showPopup(layout.getRootDiv(), element, hiddenTabs, onOverflowItemSelect, layout.getClassName);
        event.stopPropagation();
    };

    const onOverflowItemSelect = (item: { node: TabNode; index: number }) => {
        layout.doAction(Actions.selectTab(item.node.getId()));
        userControlledLeft.current = false;
    };

    const onFloatTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
        const selectedTabNode = border.getChildren()[border.getSelected()] as TabNode;
        if (selectedTabNode !== undefined) {
            layout.doAction(Actions.floatTab(selectedTabNode.getId()));
        }
        event.stopPropagation();
    };

    const cm = layout.getClassName;

    let style = border.getTabHeaderRect()!.styleWithPosition({});
    const tabs: any = [];

    const layoutTab = (i: number) => {
        let isSelected = border.getSelected() === i;
        let child = border.getChildren()[i] as TabNode;

        tabs.push(
            <BorderButton
                layout={layout}
                border={border.getLocation().getName()}
                node={child}
                path={path + "/tb" + i}
                key={child.getId()}
                selected={isSelected}
                iconFactory={iconFactory}
                titleFactory={titleFactory}
                icons={icons}
            />
        );
    };

    for (let i = 0; i < border.getChildren().length; i++) {
        layoutTab(i);
    }

    let borderClasses = cm(CLASSES.FLEXLAYOUT__BORDER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_ + border.getLocation().getName());
    if (border.getClassName() !== undefined) {
        borderClasses += " " + border.getClassName();
    }

    // allow customization of tabset right/bottom buttons
    let buttons: any[] = [];
    const renderState = { headerContent: {}, buttons, stickyButtons: [], headerButtons: [] };
    layout.customizeTabSet(border, renderState);
    buttons = renderState.buttons;

    let toolbar;

    if (hiddenTabs.length > 0) {
        const overflowTitle = layout.i18nName(I18nLabel.Overflow_Menu_Tooltip);
        buttons.push(
            <button
                key="overflowbutton"
                ref={overflowbuttonRef}
                className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW_ + border.getLocation().getName())}
                title={overflowTitle}
                onClick={onOverflowClick}
                onMouseDown={onInterceptMouseDown}
                onTouchStart={onInterceptMouseDown}
            >
                {icons?.more}
                {hiddenTabs.length}
            </button>
        );
    }

    const selectedIndex = border.getSelected();
    if (selectedIndex !== -1) {
        const selectedTabNode = border.getChildren()[selectedIndex] as TabNode;
        if (selectedTabNode !== undefined && layout.isSupportsPopout() && selectedTabNode.isEnableFloat() && !selectedTabNode.isFloating()) {
            const floatTitle = layout.i18nName(I18nLabel.Float_Tab);
            buttons.push(
                <button
                    key="float"
                    title={floatTitle}
                    className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_FLOAT)}
                    onClick={onFloatTab}
                    onMouseDown={onInterceptMouseDown}
                    onTouchStart={onInterceptMouseDown}
                />
            );
        }
    }
    toolbar = (
        <div key="toolbar" ref={toolbarRef} className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_ + border.getLocation().getName())}>
            {buttons}
        </div>
    );

    style = layout.styleFont(style);

    let innerStyle = {};
    const borderHeight = border.getBorderBarSize() - 1;
    if (border.getLocation() === DockLocation.LEFT) {
        innerStyle = { right: borderHeight, height: borderHeight, top: position };
    } else if (border.getLocation() === DockLocation.RIGHT) {
        innerStyle = { left: borderHeight, height: borderHeight, top: position };
    } else {
        innerStyle = { height: borderHeight, left: position };
    }

    return (
        <div ref={selfRef} dir="ltr" style={style} className={borderClasses} 
            data-layout-path={path}
            onClick={onAuxMouseClick}
            onAuxClick={onAuxMouseClick}
            onContextMenu={onContextMenu}
            onWheel={onMouseWheel}>
            <div style={{ height: borderHeight }} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_ + border.getLocation().getName())}>
                <div style={innerStyle} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER_ + border.getLocation().getName())}>
                    {tabs}
                </div>
            </div>
            {toolbar}
        </div>
    );
};
