import { KeyboardEvent, MouseEvent, useCallback } from 'react'
import styled from 'styled-components'

import { InferComponentProps } from '../types.js'
import { Input } from '../input.js'
import { IconButton } from '../icon-button'

const StyledIconButton = styled(IconButton)`
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  width: 24px;
`

type InputWithSensitivityButtonProps = {
  isVisible: boolean
  onToggle: () => void
} & InferComponentProps<typeof Input>

const _InputWithSensitivityButton = ({ isVisible, onToggle, ...props }: InputWithSensitivityButtonProps) => {
  const onKeyboard = useCallback(
    (e: KeyboardEvent) => {
      if (e.key === ' ' || e.key === 'Enter') {
        onToggle && onToggle()
      }
    },
    [onToggle]
  )

  const onMouse = useCallback(
    (e: MouseEvent) => {
      if (e.button === 0) {
        onToggle && onToggle()
      }
    },
    [onToggle]
  )

  return (
    <Input data-testid={`input-with-sensitivity-button: ${props.name}`} {...props}>
      <StyledIconButton
        name={isVisible ? 'feedback/invisible' : 'feedback/visible'}
        /* Using onToggle instead of onClick.  When using on click, the following occurs:
         * 1. on mouse down, the onBlur of the input fires and calls field.onBlur - this triggers a state update
         * 2. the component rerenders - this means this Icon component rerenders.  The element is swapped out with
         * a new identical element
         * 3. on mouse up, the browser does not send the onClick event because the element is different. On click
         * requires a mouse-down followed by a mouse-up on the same element
         *
         * Using React.memo(VisibilityIconComponent) also works
         */
        onMouseDown={onMouse}
        onKeyPress={onKeyboard}
      />
    </Input>
  )
}

export const InputWithSensitivityButton = styled(_InputWithSensitivityButton)``
