import React, { Component, type JSX } from 'react';
import AutoCompleteStatus from '@digigov/react-core/AutoCompleteStatus';
import AutoCompleteStatusContainer from '@digigov/react-core/AutoCompleteStatusContainer';

const debounce = function (
  func: () => void,
  wait: number,
  immediate?: boolean
) {
  let timeout;
  return function (...args) {
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const context = this;
    const later = function () {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
    return timeout;
  };
};
const statusDebounceMillis = 1400;

interface StatusProps {
  id: string;
  length: number;
  queryLength: number;
  minQueryLength?: number;
  selectedOption: string;
  selectedOptionIndex: number;
  validChoiceMade: boolean;
  isInFocus: boolean;
  tQueryTooShort?: (x: number) => string;
  tNoResults?: () => string;
  tSelectedOption: (x: string, y: number, z: number) => string;
  tResults?: (x: number, y: string) => string;
}

interface StateProps {
  bump: boolean;
  debounced: boolean;
  silenced: boolean;
}

export default class Status extends Component<StatusProps, StateProps> {
  static defaultProps = {
    tQueryTooShort: (minQueryLength: number): string =>
      `Type in ${minQueryLength} or more characters for results`,
    tNoResults: (): string => 'No search results',
    tSelectedOption: (
      selectedOption: string,
      length: number,
      index: number
    ): string => `${selectedOption} ${index + 1} of ${length} is highlighted`,
    tResults: (length: number, contentSelectedOption: string): string => {
      const words = {
        result: length === 1 ? 'result' : 'results',
        is: length === 1 ? 'is' : 'are',
      };

      return `${length} ${words.result} ${words.is} available. ${contentSelectedOption}`;
    },
  };

  state = {
    bump: false,
    debounced: false,
    silenced: false,
  };
  debounceStatusUpdate: () => void;
  lastDebounceCall: any;
  componentWillUnmount(): void {
    clearTimeout(this.lastDebounceCall);
  }
  UNSAFE_componentWillMount() {
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const that = this;
    this.debounceStatusUpdate = debounce(function () {
      if (!that.state.debounced) {
        const shouldSilence =
          !that.props.isInFocus || that.props.validChoiceMade;
        that.setState(({ bump }) => ({
          bump: !bump,
          debounced: true,
          silenced: shouldSilence,
        }));
      }
    }, statusDebounceMillis);
  }

  UNSAFE_componentWillReceiveProps() {
    this.setState({ debounced: false });
  }

  render(): JSX.Element {
    const {
      id,
      length,
      queryLength,
      minQueryLength,
      selectedOption,
      selectedOptionIndex,
      tQueryTooShort,
      tNoResults,
      tSelectedOption,
      tResults,
    } = this.props;
    const { bump, debounced, silenced } = this.state;

    const queryTooShort = queryLength < (minQueryLength as number);
    const noResults = length === 0;

    const contentSelectedOption = selectedOption
      ? tSelectedOption(selectedOption, length, selectedOptionIndex)
      : '';

    let content;
    if (queryTooShort) {
      content = tQueryTooShort?.(minQueryLength as number);
    } else if (noResults) {
      content = tNoResults?.();
    } else {
      content = tResults?.(length, contentSelectedOption);
    }

    this.lastDebounceCall = this.debounceStatusUpdate();

    return (
      <AutoCompleteStatusContainer>
        <AutoCompleteStatus id={id + '__status--A'}>
          {!silenced && debounced && bump ? content : ' '}
        </AutoCompleteStatus>
        <AutoCompleteStatus id={id + '__status--B'}>
          {!silenced && debounced && !bump ? content : ' '}
        </AutoCompleteStatus>
      </AutoCompleteStatusContainer>
    );
  }
}

export { AutoCompleteStatusContainer, AutoCompleteStatus };
