// @flow
import React, { useCallback, useState, useMemo } from 'react';
import styled from 'styled-components';
import { v4 } from 'uuid';
import { FieldLabel } from '../../typography';
import { Box, HideAccessibly } from '../../../primitives';
import { getPaletteColor } from '../../../mixins/branding';
import {
  getFontSize,
  getFontFamily,
  getFontWeight,
} from '../../../mixins/typography';

import type { SearchInputFieldProps } from './search-input-field.proptypes';
import {
  LeftStyledSearchIcon,
  RightStyledSearchIcon,
  ClearInputButton,
} from './icons';

import {
  getSearchInputLeftPadding,
  getSearchInputFocusedLeftPadding,
} from './search-input-field.css-rules';

export const getInputHeight = ({ large }: SearchInputFieldProps) =>
  large ? '60px' : '40px';

const StyledSearchInputField = styled.input.attrs(({ bold, large }) => ({
  fontSize: large ? 'f3' : 'f1',
  bold: large ? 'true' : bold,
}))`
  && {
    background-color: ${getPaletteColor('white')};
    background-repeat: no-repeat;
    border: 1px solid ${getPaletteColor('greyscale-light')};
    border-radius: 6px;
    color: ${getPaletteColor('greyscale-black')};
    font-family: ${getFontFamily};
    font-size: ${getFontSize};
    font-weight: ${getFontWeight};
    height: ${getInputHeight};
    padding: 0;
    padding-left: ${getSearchInputLeftPadding};
    padding-right: 40px;
    width: 100%;

    &&::placeholder {
      /* Chrome, Firefox, Opera, Safari 10.1+ */
      color: ${getPaletteColor('greyscale-dark')};
      opacity: 1; /* Firefox */
      font-style: italic;
    }

    &:focus {
      border: 1px solid ${getPaletteColor('greyscale-medium')};
      outline: none;
      padding-left: ${getSearchInputFocusedLeftPadding};

      &&::placeholder {
        color: transparent;
        opacity: 0; /* Firefox */
      }
    }
  }
`;

const SearchInputIcon = ({
  focused,
  hasValue,
  large,
}: {|
  focused: boolean,
  hasValue: boolean,
  large: boolean,
|}) => {
  const showGreySearchIcon = !focused && !hasValue;
  const showFocusedSearchIcon = focused && !hasValue;
  if (showGreySearchIcon) {
    return <LeftStyledSearchIcon large={large} />;
  }
  if (showFocusedSearchIcon) {
    return <RightStyledSearchIcon large={large} />;
  }
  return null;
};

const SearchInputFieldContainer = styled(Box)`
  position: relative;
`;

export const SearchInputField = ({
  value,
  large = false,
  bold = false,
  hideLabel = false,
  clearLabel,
  label,
  placeholder,
  onChange,
  onClear,
  focusOnMount,
  spacing,
  grow,
  shrink,
  basis,
  onFocus,
  onBlur,
  className,
  'data-qa': dataQa,
  'data-cy': dataCy,
  id,
  name,
  isExpanded = false,
  resultsListId,
  ...props
}: SearchInputFieldProps) => {
  // Focused state
  const [focused, setFocused] = useState(false);
  const handleSearchInputFocused = useCallback(
    (e) => {
      setFocused(true);
      if (onFocus) onFocus(e);
    },
    [setFocused, onFocus],
  );
  const handleSearchInputBlurred = useCallback(
    (e) => {
      setFocused(false);

      if (onBlur) onBlur(e);
    },
    [setFocused, onBlur],
  );

  const handleOnChange = useCallback(
    (evt) => {
      onChange(evt.target.value, evt);
    },
    [onChange],
  );

  const handleClear = useCallback(() => {
    onChange('');
    if (onClear) {
      onClear();
    }
  }, [onClear, onChange]);

  const inputId = useMemo(() => `input-${v4()}`, []);
  const inputProps = {
    id: inputId,
    name,
    large,
    bold: bold ? 'true' : undefined,
    type: 'text',
    value,
    autoFocus: focusOnMount,
    onChange: handleOnChange,
    onBlur: handleSearchInputBlurred,
    onFocus: handleSearchInputFocused,
    placeholder,
    hasDarkIcon: !!value,
  };

  return (
    <SearchInputFieldContainer
      {...{ spacing, grow, shrink, basis }}
      className={className}
      data-cy={dataCy}
      data-qa={dataQa}
      id={id}
      {...props}
    >
      {hideLabel ? (
        <HideAccessibly>
          <FieldLabel htmlFor={inputId}>{label}</FieldLabel>
        </HideAccessibly>
      ) : (
        <FieldLabel htmlFor={inputId} large={large}>
          {label}
        </FieldLabel>
      )}
      <div style={{ position: 'relative' }}>
        <SearchInputIcon
          focused={focused}
          hasValue={!!value.length}
          large={large}
        />
        <StyledSearchInputField
          role="combobox"
          aria-autocomplete="list"
          aria-expanded={isExpanded}
          aria-owns={resultsListId}
          autoComplete="off"
          autoCapitalize="none"
          spellCheck={false}
          {...inputProps}
        />
        <ClearInputButton
          large={large}
          onClick={handleClear}
          show={!!value.length}
          label={clearLabel == null ? 'Clear value' : clearLabel}
        />
      </div>
    </SearchInputFieldContainer>
  );
};

SearchInputField.displayName = 'SearchInputField';
