// @flow
import React, { useState, useRef, useLayoutEffect, useMemo } from 'react';
import { v4 } from 'uuid';
import styled from 'styled-components';
import type { TextAreaProps } from './text-area.proptypes';
import { Box } from '../../../primitives';
import { FieldLabel } from '../../typography/field-label';
import { HideAccessibly } from '../../../primitives/hide-accessibly';
import { getPaletteColor } from '../../../mixins/branding';
import {
  getFontSize,
  getFontFamily,
  getFontWeight,
} from '../../../mixins/typography';
import {
  FOCUS_VISIBLE_SELECTOR,
  getBaseFocusState,
} from '../../../mixins/focus';
import {
  getTextareaHeight,
  getResizable,
  getTextColor,
} from './text-area.css-rules';
import { getSpacingRules } from '../../../mixins/spacing';
import { getStackeeRules } from '../../../mixins/stackee';

export const StyledTextarea = styled.textarea.attrs(() => ({
  fontSize: 'f1',
}))`
  width: 100%;
  height: ${getTextareaHeight};
  color: ${getTextColor};
  font-family: ${getFontFamily};
  font-size: ${getFontSize};
  font-weight: ${getFontWeight};
  border-radius: 6px;
  border: 1px solid ${getPaletteColor('greyscale-light')};
  padding: 10px 20px;
  resize: ${getResizable};
  ${getBaseFocusState({
    hoverTransition: false,
    activeTransition: false,
    pointerCursor: false,
  })}
  ${FOCUS_VISIBLE_SELECTOR} {
    border: 1px solid ${getPaletteColor('greyscale-dark')};
  }
  &:not([disabled]):hover {
    border: 1px solid ${getPaletteColor('greyscale-medium')};
  }

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

  &&::-ms-input-placeholder {
    /* Microsoft Edge */
    font-style: italic;
    color: ${getPaletteColor('greyscale-dark')};
  }

  &&:-ms-input-placeholder {
    /* Internet Explorer 10-11 */
    font-style: italic;
    color: ${getPaletteColor('greyscale-dark')};
  }
`;

const TextAreaContainer = styled(Box)`
  &&& {
    ${getSpacingRules};
  }
  ${getStackeeRules};
`;

export const TextArea = ({
  id = '',
  name,
  placeholder,
  label,
  value,
  disabled,
  focusOnMount,
  resize = false,
  hideLabel = false,
  height,
  onChange = (
    _value: string,
    _event: SyntheticInputEvent<HTMLInputElement>,
  ) => {},
  onBlur = () => {},
  onFocus = () => {},
  className,
  spacing,
  grow,
  shrink,
  basis,
  'data-qa': dataQa,
  'data-cy': dataCy,
  ...props
}: TextAreaProps<string>) => {
  const textareaId = useMemo(() => `textarea-${id}-${v4()}`, [id]);
  const [managedValue, setValue] = useState(value);

  const handleChange = (evt) => {
    const newValue = evt.target.value;
    onChange(newValue, evt);
    setValue(newValue);
  };
  const textareaRef = useRef();
  useLayoutEffect(() => {
    if (focusOnMount && textareaRef.current) {
      textareaRef.current.focus();
    }
  }, [focusOnMount]);

  return (
    <TextAreaContainer
      stacked="column"
      className={className}
      {...{ spacing, grow, shrink, basis }}
      data-cy={dataCy}
      data-qa={dataQa}
      id={id}
      {...props}
    >
      {hideLabel ? (
        <HideAccessibly>
          <FieldLabel htmlFor={textareaId}>{label}</FieldLabel>
        </HideAccessibly>
      ) : (
        <FieldLabel htmlFor={textareaId}>{label}</FieldLabel>
      )}

      <StyledTextarea
        ref={textareaRef}
        id={textareaId}
        name={name}
        resize={resize}
        placeholder={placeholder}
        value={managedValue}
        height={height}
        focusOnMount={focusOnMount}
        onChange={handleChange}
        onBlur={onBlur}
        onFocus={onFocus}
        disabled={disabled}
      />
    </TextAreaContainer>
  );
};

TextArea.displayName = 'TextArea';
