/* eslint-disable no-useless-escape */
// @flow
import React, { useState } from 'react';
import styled from 'styled-components';
import ErrorMessage from './ErrorMessage';
import ApoliticalBrand from '../../../Theme/ApoliticalBrand';

const { color } = ApoliticalBrand;

const Input = styled.input`
  width: 290px;
  height: 40px;
  border-radius: 6px;
  border: 1px solid ${({ valid }) => (valid ? color.lightDarkGrey : color.invalidRed)};
  color: ${color.charcoal};
  margin-top: 6px;
  font-size: 16px;
  font-weight: 300;
  padding-left: 16px;
  padding-right: 16px;
  cursor: text;

  &:focus {
    border: 1px solid ${color.focusTeal};
    outline: none;
  }
`;
const Label = styled.label`
  text-transform: uppercase;
  color: ${({ labelColor }) => (labelColor || `${color.gunmetal}`)};
  height: 15px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 1.71px;
  max-width: 290px;
`;

const PaddingBox = styled.div`
  margin-top: 5px;
  height: 15.4px;
  content: '';
`;
type Props = {|
  /** Type. Can be 'email','text', 'url' for validation purposes.
   * Anything else will allow any kind of input in field, and will not validate.
   *  Required. */
  type: string,
  /** For accessibility, links label to input. Required. */
  inputName: string,
  /** Optional placeholder text for the input field */
  placeholderText: ?any,
  /** Label children will usually be a string,
   * but this will allow for the inclusion of a radio button also */
  labelChildren: any,
  /** Is the field a required field */
  required: ?boolean,
  /** Allows us to extend the component */
  className: ?any,
  /** Optional. allows you to pass a React.createRef into the input field */
  parentRef: ?any,
  /** Allows passing in an extra onBlur function */
  onBlur?: () => void,
  /** Allows passing in an optional onChange function */
  onChange?: () => void,
  /** Passed if using input type text,
   *  but we still want to be able to enter numbers in the field */
  numberAllowed?: ?boolean,
|};

/**
 * The input through which you can search
 */
const InputField = ({
  inputName,
  placeholderText,
  labelChildren,
  required,
  type,
  className,
  parentRef,
  onBlur,
  onChange,
  numberAllowed,
  ...props
}: Props) => {
  const [validationMessage, setValidationMessage] = useState();
  const [validity, setValidity] = useState(true);
  const inputRef = parentRef;
  const inputType = numberAllowed ? 'default' : type;

  let regex;
  let pattern;
  let invalidMessage;
  let emptyMessage;

  const validationFunction = (value) => {
    const isValid = regex.test(value);
    if (value && !isValid) {
      setValidationMessage(invalidMessage);
      setValidity(isValid);
    } else if ((required && !isValid) || (required && value.length < 1)) {
      setValidationMessage(emptyMessage);
      setValidity(!validity);
    } else {
      setValidity(validity);
      setValidationMessage();
    }
  };

  const handleBlur = (value) => {
    validationFunction(value);
    if (onBlur) {
      onBlur();
    }
  };

  const focusFunction = () => {
    setValidity(true);
    setValidationMessage();
  };

  switch (inputType) {
    case 'email':
      // Email regex based on Auth0's email validity check
      // https://github.com/auth0/lock/blob/4aaefa4a9ed00423e665e0743a7b0a952c6a267d/src/field/email.js#L7
      regex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
      pattern = '^(([^<>()[\\]\\.,;:\\s@"]+(.[^<>()[\\]\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
      invalidMessage = 'Please enter a valid email';
      emptyMessage = 'This is a required field';
      break;
    case 'text':
      regex = (/^([^0-9]*)$/);
      pattern = '^([^0-9]*)$';
      invalidMessage = 'Numbers are not allowed in this text field';
      emptyMessage = 'This is a required field';
      break;
    case 'url':
      regex = (/^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/);
      pattern = '^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&\'\(\)\*\+,;=.]+$';
      invalidMessage = 'Please enter a valid URL';
      emptyMessage = 'This is a required field';
      break;
    default:
      regex = (/[\s\S]*/);
      invalidMessage = '';
      emptyMessage = 'This is a required field';
      break;
  }

  return (
    <div className={className}>
      <Label htmlFor={inputName}>{labelChildren}</Label>
      <Input
        type={type}
        name={inputName}
        id={inputName}
        placeholder={placeholderText}
        required={required}
        onBlur={type && ((event) => handleBlur(event.target.value))}
        onFocus={focusFunction}
        valid={validity}
        ref={inputRef}
        pattern={pattern}
        onChange={onChange}
        {...props}
      />
      {!validity ? (
        <ErrorMessage validationMessage={validationMessage} />
      ) : (
        <PaddingBox />
      )}
    </div>
  );
};

InputField.defaultProps = {
  onBlur() {},
  onChange() {},
  numberAllowed: false,
};

export default InputField;
