import React from 'react'
import {Button, Panel, PanelHeading, PanelBlock} from 'bloomer'
import {FaPlus, FaEdit, FaTimes} from 'react-icons/fa'
import {Link} from '../components'

export interface ICRUDListProps<T> {
  nameKey: keyof T
  editLink?: (item: T) => string
  itemIds: ReadonlyArray<number>
  itemsById: Record<number, T>
  newLink?: string
  onRemove?: (t: T) => void
  title: string
  Info?: React.ComponentType<ICRUDItemInfoProps<T>>
  RowButtons?: React.ComponentType<ICRUDRowButtons<T>>
}

export interface ICRUDRowButtons<T> {
  item: T
}

export interface ICRUDItemRowProps<T> {
  Info?: React.ComponentType<ICRUDItemInfoProps<T>>
  RowButtons?: React.ComponentType<ICRUDRowButtons<T>>
  nameKey: keyof T
  editLink?: string
  item: T
  onRemove?: (t: T) => void
}

export interface ICRUDItemInfoProps<T> {
  item: T
  nameKey: keyof T
}

export class CRUDItemInfo<T>
extends React.PureComponent<ICRUDItemInfoProps<T>> {
  render() {
    const {item, nameKey} = this.props
    return <span>{item[nameKey]}</span>
  }
}

export class CRUDItemRow<T> extends React.PureComponent<ICRUDItemRowProps<T>> {
  handleRemove = () => {
    const {onRemove, item} = this.props
    if (onRemove) {
      onRemove(item)
    }
  }
  render() {
    const {nameKey, editLink, item} = this.props

    return (
      <React.Fragment>
        <div className='item-info'>
          {this.props.Info
            ? <this.props.Info item={item} nameKey={nameKey} />
            : <CRUDItemInfo<T> item={item} nameKey={nameKey} />
          }
        </div>
        <div className='ml-auto'>
          {!!this.props.RowButtons && (
            <this.props.RowButtons item={item} />
          )}
          &nbsp;
          {!!editLink && (
            <Link to={editLink}>
              <Button isInverted isColor='link' aria-label='Edit'>
                <FaEdit />
              </Button>
            </Link>
          )}
          &nbsp;
          {!!this.props.onRemove && (
            <Button
              aria-label='Remove'
              onClick={this.handleRemove}
              isColor='danger'
              isInverted
            >
              <FaTimes />
            </Button>
          )}
        </div>
      </React.Fragment>
    )
  }
}

export class CRUDList<T> extends React.PureComponent<ICRUDListProps<T>> {
  render() {
    const {nameKey, editLink, itemIds, itemsById, newLink, title} = this.props

    return (
      <Panel>
        <PanelHeading>
          <span className='is-flex v-centered'>
            <span>{title}</span>
            {!!newLink && (
              <Link
                className='ml-auto button is-link is-small'
                to={newLink}
              >
                <FaPlus />&nbsp; New
              </Link>
            )}
          </span>
        </PanelHeading>
        {itemIds.map(itemId => {
          const item = itemsById[itemId]
          return (
            <PanelBlock key={itemId}>
              <CRUDItemRow<T>
                Info={this.props.Info}
                RowButtons={this.props.RowButtons}
                nameKey={nameKey}
                editLink={editLink && editLink(item)}
                item={item}
                onRemove={this.props.onRemove}
              />
            </PanelBlock>
          )
        })}
      </Panel>
    )
  }
}
