import * as React from 'react';
import classnames from 'classnames';
import { CnBalloon } from '@alife/cn-ui';
import { CnBalloonProps } from '@alife/cn-ui/es/components/cn-balloon/index';
import keyboardEvent from '../event';

import './index.scss';

type ChangeEvent = KeyboardEvent | React.MouseEvent;

export type SwitchChangeEventHandler = (
  checked: boolean,
  event?: ChangeEvent,
) => void;

export interface SwitchProps {
  /** 按钮文字 */
  text?: string;
  /** 快捷键 */
  hotKey?: string;
  size?: 'small' | 'medium';
  /** 点击按钮触发函数 */
  onChange?: SwitchChangeEventHandler;
  /** 开关值 */
  value?: boolean;
  /** 是否只读 */
  readOnly?: boolean;
  /** 表示开关被禁用 */
  disabled?: boolean;
  /** 自定义类名 */
  className?: string;
  /** 自定义内联样式 */
  style?: React.CSSProperties;
  /** 气泡提示 */
  balloon?: CnBalloonProps;
}

export default function Switch(props: SwitchProps) {
  const {
    value,
    text,
    hotKey,
    readOnly,
    onChange,
    className,
    size = 'small',
    balloon = {},
    ...others
  } = props;

  const doChange = React.useCallback(
    (e?: ChangeEvent) => {
      onChange instanceof Function && onChange(!value, e);
    },
    [value, onChange],
  );

  React.useEffect(() => {
    if (hotKey && !readOnly && onChange) {
      const formatHotKey = hotKey.toLocaleLowerCase();
      keyboardEvent.bind(formatHotKey, doChange);
      return () => {
        keyboardEvent.unbind(formatHotKey, doChange);
      };
    }
    return () => {};
  }, [hotKey, readOnly, onChange, doChange]);

  const switchBtn = (
    <div
      data-hottag='cn-op.switch'
      className={classnames('op-switch', `op-switch-${size}`, className)}
      {...others}
    >
      {readOnly ? (
        value && <span className='op-switch-label'>{text ?? ''}</span>
      ) : (
        <>
          <div
            className={classnames(
              'op-switch-inner',
              `op-switch-inner-${value ? 'on' : 'off'}`,
            )}
            onClick={doChange}
          >
            <div className='op-switch-inner-btn' />
          </div>
          {text && (
            <span className='op-switch-label'>
              {text ?? ''}
              {hotKey ? `[${hotKey}]` : ''}
            </span>
          )}
        </>
      )}
    </div>
  );

  const { children: balloonChildren, ...rest } = balloon;
  return balloonChildren ? (
    <CnBalloon
      v2
      className='op-balloon'
      triggerType='hover'
      align='tl'
      closable={false}
      trigger={switchBtn}
      {...rest}
    >
      {balloonChildren}
    </CnBalloon>
  ) : (
    switchBtn
  );
}
