import { Component, ElementType, ReactNode } from 'react';
import classNames from 'classnames';
import FilledButton from './filled-button';
import FlatButton from './flat-button';
import OutlineButton from './outline-button';

type ButtonProps = {
  content?: string;
  color?: string;
  colorWeight?: number;
  borderWeight?: number;
  textColor?: string;
  textColorWeight?: string;
  type?: 'button' | 'submit' | 'reset';
  onClick?: () => void;
  children?: ReactNode;
  inline?: boolean;
  outline?: boolean;
  flat?: boolean;
  size?: 'zero' | 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';
  textSize?: 'xs' | 'sm' | 'base' | 'lg' | 'xl';
  justifyContent?: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
  loading?: boolean;
  disabled?: boolean;
  circular?: boolean;
  className?: string;
};

class Button extends Component<ButtonProps> {
  static defaultProps = {
    type: 'button',
    inline: false,
    outline: false,
    flat: false,
    size: 'base',
    textSize: 'sm',
    justifyContent: 'center',
    color: 'blue',
    colorWeight: 500,
    borderWeight: 1,
    loading: false,
    disabled: false
  };

  getSizeClass = () => {
    const sizePaddingMap = {
      default: {
        zero: `p-0`,
        xs: 'py-0.5 px-1',
        sm: 'py-1 px-2',
        base: 'py-1.5 px-3',
        lg: 'py-2 px-4',
        xl: 'py-2.5 px-5',
        '2xl': 'py-3 px-6',
        '3xl': 'py-3.5 px-7',
        '4xl': 'py-4 px-8'
      },
      circular: {
        zero: `p-0`,
        xs: 'p-0.5 min-w-[2rem] min-h-[2rem]',
        sm: 'p-1 min-w-[4rem] min-h-[4rem]',
        base: 'p-1.5 min-w-[6rem] min-h-[6rem]',
        lg: 'p-2 min-w-[8rem] min-h-[8rem]',
        xl: 'p-2.5 min-w-[10rem] min-h-[10rem]',
        '2xl': 'p-3 min-w-[12rem] min-h-[12rem]',
        '3xl': 'p-3.5 min-w-[14rem] min-h-[14rem]',
        '4xl': 'p-4 min-w-[16rem] min-h-[16rem]'
      }
    };
    const { size = 'base', textSize = 'sm', circular = false } = this.props;
    return `text-${textSize} ${sizePaddingMap[circular ? 'circular' : 'default'][size]} ${
      circular ? 'rounded-full' : 'rounded-md'
    }`;
  };

  getContainer: () => ElementType = () => {
    const { flat = false, outline = false } = this.props;
    if (flat) return FlatButton;
    if (outline) return OutlineButton;
    return FilledButton;
  };

  render() {
    const Container = this.getContainer();

    return (
      <Container
        {...this.props}
        className={classNames(
          this.getSizeClass(),
          this.props.inline ? 'inline-flex' : 'flex',
          `justify-${this.props.justifyContent} items-center`,
          this.props.className
        )}
      >
        {this.props.content !== undefined ? this.props.content : this.props.children}
        {this.props.loading && (
          <svg
            className='-ml-1 mr-3 h-5 w-5 animate-spin text-white'
            xmlns='http://www.w3.org/2000/svg'
            fill='none'
            viewBox='0 0 24 24'
          >
            <circle
              className='opacity-25'
              cx='12'
              cy='12'
              r='10'
              stroke='currentColor'
              strokeWidth='4'
            />
            <path
              className='opacity-75'
              fill='currentColor'
              d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z'
            />
          </svg>
        )}
      </Container>
    );
  }
}

export default Button;
