// @ts-nocheck
import React, { Fragment, useState, useRef } from 'react'
import { Listbox, Transition } from '@headlessui/react'
import { CheckIcon, SelectorIcon } from '@heroicons/react/solid'
import '../tailwind.css'

import { useField, FieldRenderProps, UseFieldConfig } from 'react-final-form'

import { classNames } from '../utils/css'
import { Labelled } from '../Labelled/Labelled'

interface StrictOption {
  /** Machine value of the option; this is the value passed to `onChange` */
  value: string
  /** Human-readable text for the option */
  label: string
  /** Option will be visible, but not selectable */
  disabled: boolean
  /** Element to display to the left of the option label. */
  prefix: React.ReactNode
}

export interface SelectProps {
  /* Additional hint text to display */
  helpText?: string
  /* Label for the input */
  label?: string
  /* Disable the input */
  disabled?: boolean
  /* Name of the input */
  name: string
  /** List of options */
  options: object[] | StrictOption[]
  /** Property of option's text value */
  optionText?: string
  /** Property of prefix value */
  prefixText?: string
  /** Property of option's value */
  valueText?: string
  /** Value for form input */
  value?: any
  // Display larger input
  large?: boolean
  /* Validation function */
  validate?: UseFieldConfig<string>['validate']
  /** Callback when value is changed */
  onChange?(value: any): void
}

const styles = {
  base: 'mt-1 relative border border-primary-border py-2 px-3 rounded-lg text-base sm:text-sm ',
  default: 'text-primary-text',
  error: 'text-negative-text',
  disabled: 'text-disabled-text',
  smallPadding: 'py-2 px-3',
  largePadding: 'py-3 px-4',
  smallFont: 'text-sm',
  largeFont: 'text-base'
}

export const Select = ({
  value,
  helpText,
  label,
  disabled,
  name,
  options,
  optionText,
  // valueText,
  prefixText,
  onChange,
  validate,
  large
}: SelectProps) => {
  const {
    input,
    meta: { error, touched, submitError }
  }: FieldRenderProps<string> = useField(name, {
    initialValue: value,
    validate: validate
  })

  const errorText = touched && (error || submitError) ? error : null
  const [selected, setSelected] = useState(input.value)
  const className = classNames(
    true && styles.base,
    !errorText && styles.default,
    errorText && styles.error,
    disabled && styles.disabled,
    !large && styles.smallPadding,
    large && styles.largePadding,
    !large && styles.smallFont,
    large && styles.largeFont
  )
  const inputNode = useRef<HTMLInputElement>(null)
  const optionKey: string = optionText ? `${optionText}` : 'value'
  const prefixKey: string = prefixText ? `${prefixText}` : 'prefix'

  const handleChange = (v: any) => {
    setSelected(v)
    input.onChange(v)
    if (onChange) {
      onChange(v)
    }
  }

  const handleClick = () => {
    inputNode.current?.focus()
  }

  return (
    <div ref={inputNode} onClick={handleClick}>
      <Listbox value={selected} disabled={disabled} onChange={handleChange}>
        {({ open }) => (
          <>
            <Listbox.Button className="w-full text-left">
              <Labelled
                label={label ? label : ''}
                helpText={helpText}
                error={errorText}
                disabled={disabled}
              >
                <div className={className}>
                  {selected[`${prefixKey}`] && (
                    <span className="mr-2">{selected[`${prefixKey}`]}</span>
                  )}{' '}
                  {selected[`${optionKey}`]}

                  <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
                    <SelectorIcon
                      className="h-5 w-5 text-secondary-text"
                      aria-hidden="true"
                    />
                  </span>
                  <Transition
                    show={open}
                    as={Fragment}
                    leave="transition ease-in duration-100"
                    leaveFrom="opacity-100"
                    leaveTo="opacity-0"
                  >
                    <Listbox.Options className="absolute left-0 z-10 mt-3 max-h-60 w-full overflow-auto rounded-lg bg-primary-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
                      {options.map((option, index) => (
                        <Listbox.Option
                          key={`${index}`}
                          className={({ active }) =>
                            classNames(
                              active
                                ? 'bg-inverted-background text-on-primary-text'
                                : 'text-primary-text',
                              'relative cursor-default select-none py-2 pl-3 pr-9'
                            )
                          }
                          value={option}
                        >
                          {({ selected, active }) => (
                            <>
                              <span
                                className={classNames(
                                  selected ? 'font-semibold' : 'font-normal',
                                  'block truncate'
                                )}
                              >
                                {option[`${prefixKey}`] && (
                                  <span className="mr-2">
                                    {option[`${prefixKey}`]}
                                  </span>
                                )}{' '}
                                {option[`${optionKey}`]}
                              </span>

                              {selected ? (
                                <span
                                  className={classNames(
                                    active
                                      ? 'text-on-primary-text'
                                      : 'text-inverted-background',
                                    'absolute inset-y-0 right-0 flex items-center pr-4'
                                  )}
                                >
                                  <CheckIcon
                                    className="h-5 w-5"
                                    aria-hidden="true"
                                  />
                                </span>
                              ) : null}
                            </>
                          )}
                        </Listbox.Option>
                      ))}
                    </Listbox.Options>
                  </Transition>
                </div>
              </Labelled>
            </Listbox.Button>
          </>
        )}
      </Listbox>
    </div>
  )
}
