import React, { useContext } from "react";
import classNames from "classnames";
import { Omit, StyledProps } from "../_type";
import { CheckProps, CheckContext } from "../check";
import { Text } from "../text";
import { useDefaultValue } from "../form/controlled";
import { callBoth } from "../_util/call-both";
import { Tooltip } from "../tooltip";
import { useConfig } from "../_util/config-context";
import { noop } from "../_util/noop";

/**
 * Switch 组件所接收的参数
 */
export interface SwitchProps
  extends Omit<CheckProps, "type" | "display" | "indeterminate">,
    StyledProps {
  /**
   * 是否处于加载中状态
   */
  loading?: boolean;
}

export const Switch = React.forwardRef(function Switch(
  props: SwitchProps,
  ref: React.Ref<HTMLLabelElement>
) {
  const { classPrefix } = useConfig();
  // 支持从 Context 注入
  const context = useContext(CheckContext);

  if (context) {
    const checkProps = context.inject({ type: "checkbox", ...props });
    delete checkProps.type;
    // eslint-disable-next-line no-param-reassign
    props = checkProps;
  }

  const {
    name,
    value,
    disabled,
    onChange = noop,
    onClick = noop,
    loading,
    tooltip,
    children,
    className,
    ...extraProps
  } = useDefaultValue(props, false);

  let component = (
    <label
      ref={children ? undefined : ref}
      className={classNames(
        `${classPrefix}-switch`,
        { "is-loading": loading },
        className
      )}
      {...(children ? {} : extraProps)}
    >
      <input
        readOnly
        type="checkbox"
        className={`${classPrefix}-switch__input`}
        checked={value}
        disabled={disabled || loading}
        onClick={callBoth(
          children ? noop : onClick,
          (event: React.MouseEvent<HTMLInputElement>) => {
            const { checked } = event.currentTarget;
            onChange(checked, {
              event,
              check: {
                type: "checkbox",
                ...props,
                value: checked,
              },
            });
          }
        )}
      />
      <span className={`${classPrefix}-switch__toggle`} />
    </label>
  );

  // 默认是不需要 children 的，如果提供了，需要包装一层
  if (children) {
    component = (
      <label
        ref={ref}
        onClick={event => {
          // 多次触发
          if ((event.target as Element)?.tagName !== "SPAN") {
            onClick(event);
          }
        }}
        style={{ cursor: disabled ? "default" : "pointer" }}
        {...extraProps}
      >
        {component}
        <Text reset style={{ verticalAlign: "middle", margin: "0 5px" }}>
          {children}
        </Text>
      </label>
    );
  }

  if (tooltip) {
    component = <Tooltip title={tooltip}>{component}</Tooltip>;
  }

  return component;
});

Switch.displayName = "Switch";
