import React from "react";
import classNames from "classnames";
import { useTranslation } from "../i18n";
import { useDefaultValue } from "../form";
import { useConfig } from "../_util/config-context";
import { NativeSelectProps } from "./SelectProps";
import { SelectOptionWithGroup } from "./SelectOption";

function groupBy(options: SelectOptionWithGroup[]): SelectOptionWithGroup[][] {
  const groups = [];
  options.forEach((opt, index) => {
    const { groupKey } = opt;
    if (index === 0 || groupKey !== options[index - 1].groupKey) {
      groups.push([]);
    }
    groups[groups.length - 1].push(opt);
  });
  return groups;
}

/**
 * 原生 Select
 */
export const NativeSelect = React.forwardRef(function NativeSelect(
  props: NativeSelectProps,
  ref: React.Ref<HTMLSelectElement>
) {
  const t = useTranslation();
  const { classPrefix } = useConfig();
  const {
    type,
    value,
    onChange,
    options = [],
    groups = {},
    placeholder = t.pleaseSelect,
    disabled,
    size,
    className,
    ...extraProps
  } = useDefaultValue(props, null);

  return (
    <select
      ref={ref}
      className={classNames(`${classPrefix}-select`, className, {
        [`size-${
          size === "full" || size === "auto" ? `${size}-width` : size
        }`]: size,
      })}
      disabled={disabled}
      value={value != null ? value : ""}
      placeholder={placeholder}
      onChange={
        disabled
          ? null
          : event => {
              const { value } = event.target;
              onChange(value, {
                event,
                option: options.find(i => i.value === value),
              });
            }
      }
      {...extraProps}
    >
      {typeof placeholder === "string" && (
        <option disabled={!!value} hidden>
          {placeholder}
        </option>
      )}
      {options.find(opt => !!opt.groupKey)
        ? groupBy(options).map(group => {
            const { value, groupKey } = group[0];
            if (!groupKey) {
              return group.map(opt => (
                <option
                  key={opt.value}
                  value={opt.value}
                  disabled={opt.disabled}
                  title={
                    typeof opt.tooltip === "string" ? opt.tooltip : undefined
                  }
                >
                  {typeof opt.text === "undefined" ? opt.value : opt.text}
                </option>
              ));
            }
            return (
              <optgroup key={value} label={(groups[groupKey] as string) || ""}>
                {group.map(opt => (
                  <option
                    key={opt.value}
                    value={opt.value}
                    disabled={opt.disabled}
                    title={
                      typeof opt.tooltip === "string" ? opt.tooltip : undefined
                    }
                  >
                    {typeof opt.text === "undefined" ? opt.value : opt.text}
                  </option>
                ))}
              </optgroup>
            );
          })
        : options.map(opt => (
            <option
              key={opt.value}
              value={opt.value}
              disabled={opt.disabled}
              title={typeof opt.tooltip === "string" ? opt.tooltip : undefined}
            >
              {typeof opt.text === "undefined" ? opt.value : opt.text}
            </option>
          ))}
    </select>
  );
});

NativeSelect.displayName = "NativeSelect";
