import React, { FC, ReactNode } from 'react'

import {
  appendVariantClasses,
  formatClassList,
  joinStrings
} from '../../utils'


type ButtonTypes = {
  children: ReactNode,
  className?: string,
  disabled?: boolean,
  size?: string,
  variant?: string,
  [other:string]: unknown
}

const BTN: string = `
  font-sans
  outline-none
  transition
  duration-200
  focus:shadow-outline
  font-normal
  relative
  tracking-wider
  overflow-hidden
`

const BASE: string = `
  shadow-md
  active:shadow-sm
`

const SM: string = `
  rounded
  text-base
  py-2
  px-2
`

const STANDARD: string = `
  rounded
  text-base
  py-3
  px-4
`

const LG: string = `
  rounded-md
  text-xl
  py-3
  px-4
`

const RED: string = `
  ${BASE}
  bg-bscs-red-600
  focus:bg-bscs-red-800
  border-bscs-red-600
  focus:border-bscs-red-800
  text-white
`

const ORANGE: string = `
  ${BASE}
  bg-bscs-orange-400
  focus:bg-bscs-orange-500
  border-bscs-orange-400
  focus:border-bscs-orange-500
  text-white
`

const YELLOW: string = `
  ${BASE}
  bg-bscs-yellow-400
  focus:bg-bscs-yellow-500
  border-bscs-yellow-400
  focus:border-bscs-yellow-500
  text-bscs-yellow-900
  focus:text-bscs-yellow-1000
`

const GREEN: string = `
  ${BASE}
  bg-bscs-green-400
  focus:bg-bscs-green-600
  border-bscs-green-400
  focus:border-bscs-green-600
  text-white
`

const BLUE: string = `
  ${BASE}
  bg-bscs-blue-500
  focus:bg-bscs-blue-600
  border-bscs-blue-500
  focus:border-bscs-blue-600
  text-white
`

const INDIGO: string = `
  ${BASE}
  bg-bscs-indigo-500
  focus:bg-bscs-indigo-700
  border-bscs-indigo-500
  focus:border-bscs-indigo-700
  text-white
`

const VIOLET: string = `
  ${BASE}
  bg-bscs-violet-500
  focus:bg-bscs-violet-700
  border-bscs-violet-500
  focus:border-bscs-violet-700
  text-white
`

const OUTLINE_RED: string = `
  ${BASE}
  border
  border-bscs-red-700
  text-bscs-red-700
  bg-white
`

const OUTLINE_ORANGE: string = `
  ${BASE}
  border
  border-bscs-orange-600
  text-bscs-orange-600
  bg-white
`

const OUTLINE_YELLOW: string = `
  ${BASE}
  border
  border-bscs-yellow-900
  text-bscs-yellow-900
  bg-white
`

const OUTLINE_GREEN: string = `
  ${BASE}
  border
  border-bscs-green-400
  text-bscs-green-400
  bg-white
`

const OUTLINE_BLUE: string = `
  ${BASE}
  border
  border-bscs-blue-600
  text-bscs-blue-600
  bg-white
`

const OUTLINE_INDIGO: string = `
  ${BASE}
  border
  border-bscs-indigo-800
  text-bscs-indigo-800
  bg-white
`

const OUTLINE_VIOLET: string = `
  ${BASE}
  border
  border-bscs-violet-700
  text-bscs-violet-700
  bg-white
`

const NAKED: string = `
  text-bscs-indigo-800
`

const DISABLED: string = `
  cursor-not-allowed
  opacity-50
`

const VARIANTS: Record<string, string> = {
  'naked': NAKED,
  'outlineyellow': OUTLINE_YELLOW,
  'outlineviolet': OUTLINE_VIOLET,
  'outlineorange': OUTLINE_ORANGE,
  'outlinered': OUTLINE_RED,
  'outlinegreen': OUTLINE_GREEN,
  'outlineblue': OUTLINE_BLUE,
  'outlineindigo': OUTLINE_INDIGO,
  'yellow': YELLOW,
  'violet': VIOLET,
  'orange': ORANGE,
  'red': RED,
  'green': GREEN,
  'blue': BLUE,
  'indigo': INDIGO
}

const SIZES: Record<string, string> = {
  'sm': SM,
  'lg': LG,
  'standard': STANDARD
}

const Button:FC<ButtonTypes> = ({
  children,
  className,
  disabled=false,
  size='standard',
  variant='indigo',
  ...other
}: ButtonTypes) => {
  variant = variant.replace(/-/g, '').toLowerCase()

  let classList: string = formatClassList(
    appendVariantClasses(
      appendVariantClasses(
        (disabled ? joinStrings(' ', BTN, DISABLED) : BTN),
        VARIANTS,
        variant
      ),
      SIZES,
      size
    )
  )

  if (className) {
    classList = joinStrings(' ', classList, className)
  }

  return (
    <button
      className={classList}
      disabled={disabled}
      type="button"
      {...other}
    >
      <span>{children}</span>
    </button>
  )
}

export default Button
