import {
  Dropdown,
  ICommandBarItemProps,
  IComponentAsProps,
  IconType,
  IDropdownOption,
  IDropdownStyles,
  TooltipHost,
} from "@fluentui/react";
import { KeyboardHandlerMap } from "KeyboardShortcuts";
import * as React from "react";
import _ from "underscore";
import ChevronDownIcon from "../../../../images/Chevron_down.svg";

import { StyleConstants } from "../../../Common/StyleConstants";
import { configContext, Platform } from "../../../ConfigContext";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";

/**
 * Convert our NavbarButtonConfig to UI Fabric buttons
 * @param btns
 */
export const convertButton = (btns: CommandButtonComponentProps[], backgroundColor: string): ICommandBarItemProps[] => {
  const buttonHeightPx =
    configContext.platform == Platform.Fabric
      ? StyleConstants.FabricCommandBarButtonHeight
      : StyleConstants.CommandBarButtonHeight;

  const hoverColor =
    configContext.platform == Platform.Fabric ? StyleConstants.FabricAccentLight : StyleConstants.AccentLight;

  const getFilter = (isDisabled: boolean): string => {
    if (isDisabled) {
      return StyleConstants.GrayScale;
    }
    return configContext.platform == Platform.Fabric ? StyleConstants.FabricToolbarIconColor : undefined;
  };

  return btns
    .filter((btn) => btn)
    .map((btn: CommandButtonComponentProps, index: number): ICommandBarItemProps => {
      if (btn.isDivider) {
        return createDivider(btn.commandButtonLabel);
      }

      const isSplit = !!btn.children && btn.children.length > 0;
      const label = btn.commandButtonLabel || btn.tooltipText;
      const result: ICommandBarItemProps = {
        iconProps: {
          style: {
            width: StyleConstants.CommandBarIconWidth,
            alignSelf: btn.iconName ? "baseline" : undefined,
            filter: getFilter(btn.disabled),
          },
          imageProps: btn.iconSrc ? { src: btn.iconSrc, alt: btn.iconAlt } : undefined,
          iconName: btn.iconName,
        },
        onClick: btn.onCommandClick
          ? (ev?: React.MouseEvent<HTMLElement, MouseEvent> | React.KeyboardEvent<HTMLElement>) => {
              btn.onCommandClick(ev);
              TelemetryProcessor.trace(Action.ClickCommandBarButton, ActionModifiers.Mark, { label });
            }
          : undefined,
        key: `${btn.commandButtonLabel}${index}`,
        text: label,
        title: btn.tooltipText,
        name: label,
        disabled: btn.disabled,
        ariaLabel: btn.ariaLabel,
        "data-test": `CommandBar/Button:${label}`,
        buttonStyles: {
          root: {
            backgroundColor: "var(--colorNeutralBackground1)",
            height: buttonHeightPx,
            paddingRight: 0,
            paddingLeft: 0,
            borderRadius: configContext.platform == Platform.Fabric ? StyleConstants.FabricButtonBorderRadius : "0px",
            minWidth: 24,
            marginLeft: isSplit ? 0 : 5,
            marginRight: isSplit ? 0 : 5,
            color: "var(--colorNeutralForeground1)",
            selectors: {
              "&:hover": {
                backgroundColor: "var(--colorNeutralBackground1Hover)",
                color: "var(--colorNeutralForeground1)",
              },
              "&:active": {
                backgroundColor: "var(--colorNeutralBackground1Pressed)",
                color: "var(--colorNeutralForeground1)",
              },
            },
          },
          rootDisabled: {
            backgroundColor: "var(--colorNeutralBackground1)",
            pointerEvents: "auto",
            color: "var(--colorNeutralForegroundDisabled)",
          },
          splitButtonMenuButton: {
            backgroundColor: "var(--colorNeutralBackground1)",
            selectors: {
              ":hover": {
                backgroundColor: "var(--colorNeutralBackground1Hover)",
              },
            },
            width: 16,
          },
          label: {
            fontSize:
              configContext.platform == Platform.Fabric
                ? StyleConstants.DefaultFontSize
                : StyleConstants.mediumFontSize,
            color: "var(--colorNeutralForeground1)",
          },
          rootHovered: {
            backgroundColor: "var(--colorNeutralBackground1Hover)",
            color: "var(--colorNeutralForeground1)",
          },
          rootPressed: {
            backgroundColor: "var(--colorNeutralBackground1Pressed)",
            color: "var(--colorNeutralForeground1)",
          },
          splitButtonMenuButtonExpanded: {
            backgroundColor: "var(--colorNeutralBackground1Pressed)",
            selectors: {
              ":hover": {
                backgroundColor: "var(--colorNeutralBackground1Hover)",
              },
            },
          },
          splitButtonDivider: {
            display: "none",
          },
          icon: {
            paddingLeft: 0,
            paddingRight: 0,
            color: "var(--colorNeutralForeground1)",
          },
          splitButtonContainer: {
            marginLeft: 5,
            marginRight: 5,
            height: buttonHeightPx,
          },
        },
        className: btn.className,
        id: btn.id,
      };

      if (btn.tooltipContent) {
        result.title = undefined;
        result.commandBarButtonAs = (props: IComponentAsProps<ICommandBarItemProps>) => {
          const { defaultRender: DefaultRender, ...rest } = props;
          return React.createElement(
            TooltipHost,
            {
              content: btn.tooltipContent as JSX.Element,
              calloutProps: { gapSpace: 0 },
            },
            React.createElement(DefaultRender, rest),
          );
        };
      }

      if (isSplit) {
        // It's a split button
        result.split = true;

        result.subMenuProps = {
          items: convertButton(btn.children, backgroundColor),
          styles: {
            list: {
              // TODO Figure out how to do it the proper way with subComponentStyles.
              // TODO Remove all this crazy styling once we adopt Ui-Fabric Azure themes
              selectors: {
                ".ms-ContextualMenu-itemText": {
                  fontSize:
                    configContext.platform == Platform.Fabric
                      ? StyleConstants.DefaultFontSize
                      : StyleConstants.mediumFontSize,
                },
                ".ms-ContextualMenu-link:hover": { backgroundColor: hoverColor },
                ".ms-ContextualMenu-icon": { width: 16, height: 16 },
              },
            },
          },
        };

        result.menuIconProps = {
          iconType: IconType.image,
          style: {
            width: 12,
            paddingLeft: 1,
            paddingTop: 6,
            filter: getFilter(btn.disabled),
          },
          imageProps: {
            src: ChevronDownIcon,
            alt: btn.iconAlt,
          },
        };
      }

      if (btn.isDropdown) {
        const selectedChild = _.find(btn.children, (child) => child.dropdownItemKey === btn.dropdownSelectedKey);
        result.name = selectedChild?.commandButtonLabel || btn.dropdownPlaceholder;

        const dropdownStyles: Partial<IDropdownStyles> = {
          root: { margin: 5 },
          dropdown: { width: btn.dropdownWidth },
          title: { fontSize: 12, height: 30, lineHeight: 28 },
          dropdownItem: { fontSize: 12, lineHeight: 28, minHeight: 30 },
          dropdownItemSelected: { fontSize: 12, lineHeight: 28, minHeight: 30 },
        };

        const onDropdownChange = (
          event: React.FormEvent<HTMLDivElement>,
          option?: IDropdownOption,
          index?: number,
        ): void => {
          btn.children[index].onCommandClick(event);
          TelemetryProcessor.trace(Action.ClickCommandBarButton, ActionModifiers.Mark, { label: option.text });
        };

        result.commandBarButtonAs = (props: IComponentAsProps<ICommandBarItemProps>) => {
          return (
            <Dropdown
              placeholder={btn.dropdownPlaceholder}
              defaultSelectedKey={btn.dropdownSelectedKey}
              onChange={onDropdownChange}
              options={btn.children.map((child: CommandButtonComponentProps) => ({
                key: child.dropdownItemKey,
                text: child.commandButtonLabel,
              }))}
              styles={dropdownStyles}
            />
          );
        };
      }

      return result;
    });
};

export const createDivider = (key: string): ICommandBarItemProps => {
  return {
    onRender: () => (
      <div className="dividerContainer">
        <span />
      </div>
    ),
    iconOnly: true,
    disabled: true,
    key: key,
  };
};

export function createKeyboardHandlers(allButtons: CommandButtonComponentProps[]): KeyboardHandlerMap {
  const handlers: KeyboardHandlerMap = {};

  function createHandlers(buttons: CommandButtonComponentProps[]) {
    buttons.forEach((button) => {
      if (!button.disabled && button.keyboardAction) {
        handlers[button.keyboardAction] = (e) => {
          button.onCommandClick(e);

          // If the handler is bound, it means the button is visible and enabled, so we should prevent the default action
          return true;
        };
      }

      if (button.children && button.children.length > 0) {
        createHandlers(button.children);
      }
    });
  }

  createHandlers(allButtons);

  return handlers;
}
