import React, { ReactNode } from 'react'

/**
 * The unique value of current checkbox/radio. Useful for post data to the server
 *
 * checkbox/radio 的值，需要保证这个值在同一个域（所有 name 相同的 checkbox/radio 的集合）中是唯一的
 * 这个属性主要方便用于生成表单数据
 * */
declare type Value = string | number | boolean
declare type ShouldChange = boolean
interface ItemBase {
  value: Value
  /**
   * Default: '$GLOBAL'
   * */
  name?: string | number
  checked?: boolean
  disabled?: boolean
  className?: string
  hideIcon?: boolean
  checkedIcon?: ReactNode
  uncheckedIcon?: ReactNode
}
/**
 * The inner properties of radio/checkbox component instance
 *
 * radio/checkbox 组件的内在属性
 * */
declare type $RadioCheckboxItem = Required<
  Pick<ItemBase, 'name' | 'checked' | 'disabled' | 'value'>
> & {
  id: string
  update: (checked: boolean) => any
}
/**
 * The inner properties of checkbox controller component instance
 *
 * checkbox 控制组件的内在属性
 * */
declare type $CheckboxController = Pick<
  $RadioCheckboxItem,
  Exclude<keyof $RadioCheckboxItem, 'value' | 'update'>
> & {
  partial: boolean
  update(checked: boolean, partial: boolean): any
}
interface CheckboxItemProps extends ItemBase {
  label?:
    | ReactNode
    | ((item: CheckboxItemProps, isChecked: boolean) => ReactNode)
  fill?: boolean
  beforeChange?(
    toChecked: boolean,
    currItem: $RadioCheckboxItem,
    currVal: Value[],
  ): Promise<ShouldChange> | ShouldChange
  onChange?(currItem: $RadioCheckboxItem, val: Value[]): void
}
declare type CheckboxControllerProps = Pick<
  ItemBase,
  Exclude<keyof ItemBase, 'value'>
> & {
  label?:
    | ReactNode
    | ((item: CheckboxControllerProps, isChecked: boolean) => ReactNode)
  partialIcon?: ReactNode
  fill?: boolean
  beforeChange?(
    toChecked: boolean,
    currItem: $CheckboxController,
    currVal: Value[],
  ): Promise<ShouldChange> | ShouldChange
  onChange?(currItem: $CheckboxController, val: Value[]): void
}
interface RadioItemProps extends ItemBase {
  label?: ReactNode | ((item: RadioItemProps, isChecked: boolean) => ReactNode)
  beforeChange?(
    toChecked: boolean,
    currItem: $RadioCheckboxItem,
    currVal?: Value,
  ): Promise<ShouldChange> | ShouldChange
  onChange?(currItem: $RadioCheckboxItem, val?: Value): void
  disabled?: boolean
}
interface SwitchProps {
  className?: string
  /**
   * Default: true
   * */
  activeValue?: Value
  /**
   * Default: false
   * */
  inactiveValue?: Value
  value?: Value
  disabled?: boolean
  beforeChange?(val: Value): Promise<ShouldChange> | ShouldChange
  onChange?(val: Value): void
}
interface Props {
  name?: string | number
  hideIcon?: boolean
  className?: string
}
interface RadiosProps extends Props {
  value: Value
  items: Pick<RadioItemProps, Exclude<keyof RadioItemProps, 'name'>>[]
  disabled?: boolean
  onChange?(val?: Value): void
}
interface CheckboxsProps extends Props {
  value: Value[]
  items: Pick<CheckboxItemProps, Exclude<keyof CheckboxItemProps, 'name'>>[]
  onChange?(val: Value[]): void
}

declare const RadioItem: React.FC<RadioItemProps>

declare const Radios: React.FC<RadiosProps>

declare const CheckboxItem: React.FC<CheckboxItemProps>

declare const CheckboxController: React.FC<CheckboxControllerProps>
declare const Checkboxs: React.FC<CheckboxsProps>

declare const Switch: React.FC<SwitchProps>

export {
  $CheckboxController,
  $RadioCheckboxItem,
  CheckboxController,
  CheckboxControllerProps,
  CheckboxItem,
  CheckboxItemProps,
  Checkboxs,
  CheckboxsProps,
  RadioItem,
  RadioItemProps,
  Radios,
  RadiosProps,
  Switch,
  SwitchProps,
  Value,
}
