/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '@polymer/paper-input/paper-input';
import '../gr-autocomplete-dropdown/gr-autocomplete-dropdown';
import '../gr-cursor-manager/gr-cursor-manager';
import '../../../styles/shared-styles';
import {
  AutocompleteQueryStatus,
  AutocompleteQueryStatusType,
  GrAutocompleteDropdown,
} from '../gr-autocomplete-dropdown/gr-autocomplete-dropdown';
import {fire, fireEvent} from '../../../utils/event-util';
import {
  debounce,
  DelayedTask,
  ResolvedDelayedTaskStatus,
} from '../../../utils/async-util';
import {PropertyType} from '../../../types/common';
import {modifierPressed} from '../../../utils/dom-util';
import {sharedStyles} from '../../../styles/shared-styles';
import {LitElement, html, css, PropertyValues} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {ValueChangedEvent} from '../../../types/events';
import {PaperInputElement} from '@polymer/paper-input/paper-input';
import {IronInputElement} from '@polymer/iron-input';

const TOKENIZE_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
const DEBOUNCE_WAIT_MS = 200;

export type AutocompleteQuery<T = string> = (
  text: string
) => Promise<Array<AutocompleteSuggestion<T>>>;

declare global {
  interface HTMLElementTagNameMap {
    'gr-autocomplete': GrAutocomplete;
  }
  interface HTMLElementEventMap {
    'text-changed': ValueChangedEvent<string>;
    'value-changed': ValueChangedEvent<string>;
  }
}

export interface AutocompleteSuggestion<T = string> {
  name?: string;
  label?: string;
  value?: T;
  text?: string;
}

export interface AutocompleteCommitEventDetail {
  value: string;
}

export type AutocompleteCommitEvent =
  CustomEvent<AutocompleteCommitEventDetail>;

@customElement('gr-autocomplete')
export class GrAutocomplete extends LitElement {
  /**
   * Fired when a value is chosen.
   *
   * @event commit
   */

  /**
   * Fired when the user cancels.
   *
   * @event cancel
   */

  /**
   * Fired on keydown to allow for custom hooks into autocomplete textbox
   * behavior.
   *
   * @event input-keydown
   */

  /**
   * Query for requesting autocomplete suggestions. The function should
   * accept the input as a string parameter and return a promise. The
   * promise yields an array of suggestion objects with "name", "label",
   * "value" properties. The "name" property will be displayed in the
   * suggestion entry. The "label" property will, when specified, appear
   * next to the "name" as label text. The "value" property will be emitted
   * if that suggestion is selected.
   *
   * If query fails, the function should return rejected promise containing
   * an Error. The "message" property will be shown in a dropdown instead of
   * rendering suggestions.
   */
  @property({type: Object})
  query?: AutocompleteQuery = () => Promise.resolve([]);

  @query('#input') input?: PaperInputElement;

  @query('#suggestions') suggestionsDropdown?: GrAutocompleteDropdown;

  /**
   * The number of characters that must be typed before suggestions are
   * made. If threshold is zero, default suggestions are enabled.
   */
  @property({type: Number})
  threshold = 1;

  @property({type: Boolean, attribute: 'allow-non-suggested-values'})
  allowNonSuggestedValues = false;

  @property({type: Boolean})
  borderless = false;

  @property({type: Boolean})
  disabled = false;

  /**
   * Vertical offset needed for an element with 20px line-height, 4px
   * padding and 1px border (30px height total). Plus 1px spacing between
   * input and dropdown. Inputs with different line-height or padding will
   * need to tweak vertical offset.
   */
  @property({type: Number})
  verticalOffset = 31;

  @property({type: String})
  text = '';

  @property({type: String})
  placeholder = '';

  @property({type: Boolean, attribute: 'clear-on-commit'})
  clearOnCommit = false;

  /**
   * When true, tab key autocompletes but does not fire the commit event.
   * When false, tab key not caught, and focus is removed from the element.
   * See Issue 4556, Issue 6645.
   */
  @property({type: Boolean, attribute: 'tab-complete'})
  tabComplete = false;

  @property({type: String})
  value = '';

  /**
   * Multi mode appends autocompleted entries to the value.
   * If false, autocompleted entries replace value.
   */
  @property({type: Boolean})
  multi = false;

  /**
   * When true and uncommitted text is left in the autocomplete input after
   * blurring, the text will appear red.
   */
  @property({type: Boolean, attribute: 'warn-uncommitted'})
  warnUncommitted = false;

  @property({type: Boolean, attribute: 'show-blue-focus-border'})
  showBlueFocusBorder = false;

  /**
   * Invisible label for input element. This label is exposed to
   * screen readers by paper-input
   */
  @property({type: String})
  label = '';

  @state() suggestions: AutocompleteSuggestion[] = [];

  @state() queryStatus?: AutocompleteQueryStatus;

  @state() index: number | null = null;

  // Enabled to suppress showing/updating suggestions when changing properties
  // that would normally trigger the update.
  disableDisplayingSuggestions = false;

  // private but used in tests
  focused = false;

  @state() selected: HTMLElement | null = null;

  /**
   * The query id that status or suggestions correspond to.
   */
  private activeQueryId = 0;

  /**
   * Last scheduled update suggestions task.
   */
  private updateSuggestionsTask?: DelayedTask;

  // Generate ids for scheduled suggestion queries to easily distinguish them.
  private static NEXT_QUERY_ID = 1;

  private static getNextQueryId() {
    return GrAutocomplete.NEXT_QUERY_ID++;
  }

  /**
   * @return Promise that resolves when suggestions are update.
   */
  get latestSuggestionUpdateComplete():
    | Promise<ResolvedDelayedTaskStatus>
    | undefined {
    return this.updateSuggestionsTask?.promise;
  }

  get nativeInput() {
    return (this.input!.inputElement as IronInputElement)
      .inputElement as HTMLInputElement;
  }

  static override styles = [
    sharedStyles,
    css`
      paper-input.borderless {
        border: none;
        padding: 0;
      }
      paper-input {
        background-color: var(--view-background-color);
        color: var(--primary-text-color);
        border: 1px solid var(--prominent-border-color, var(--border-color));
        border-radius: var(--border-radius);
        padding: var(--spacing-s);
        --paper-input-container_-_padding: 0;
        --paper-input-container-input_-_font-size: var(--font-size-normal);
        --paper-input-container-input_-_line-height: var(--line-height-normal);
        /* This is a hack for not being able to set height:0 on the underline
            of a paper-input 2.2.3 element. All the underline fixes below only
            actually work in 3.x.x, so the height must be adjusted directly as
            a workaround until we are on Polymer 3. */
        height: var(--line-height-normal);
        --paper-input-container-underline-height: 0;
        --paper-input-container-underline-wrapper-height: 0;
        --paper-input-container-underline-focus-height: 0;
        --paper-input-container-underline-legacy-height: 0;
        --paper-input-container-underline_-_height: 0;
        --paper-input-container-underline_-_display: none;
        --paper-input-container-underline-focus_-_height: 0;
        --paper-input-container-underline-focus_-_display: none;
        --paper-input-container-underline-disabled_-_height: 0;
        --paper-input-container-underline-disabled_-_display: none;
        /* Hide label for input. The label is still visible for
           screen readers. Workaround found at:
           https://github.com/PolymerElements/paper-input/issues/478 */
        --paper-input-container-label_-_display: none;
      }
      paper-input.showBlueFocusBorder:focus {
        border: 2px solid var(--input-focus-border-color);
        /*
         * The goal is to have a thicker blue border when focused and a thinner
         * gray border when blurred. To avoid shifting neighboring elements
         * around when the border size changes, a negative margin is added to
         * compensate. box-sizing: border-box; will not work since there is
         * important padding to add around the content.
         */
        margin: -1px;
      }
      paper-input.warnUncommitted {
        --paper-input-container-input_-_color: var(--error-text-color);
        --paper-input-container-input_-_font-size: inherit;
      }
    `,
  ];

  override connectedCallback() {
    super.connectedCallback();
    document.addEventListener('click', this.handleBodyClick);
  }

  override disconnectedCallback() {
    document.removeEventListener('click', this.handleBodyClick);
    this.updateSuggestionsTask?.cancel();
    super.disconnectedCallback();
  }

  override willUpdate(changedProperties: PropertyValues) {
    if (changedProperties.has('text') || changedProperties.has('threshold')) {
      this.updateSuggestions();
    }
    if (
      changedProperties.has('suggestions') ||
      changedProperties.has('queryStatus')
    ) {
      this.updateDropdownVisibility();
    }
    if (changedProperties.has('text')) {
      fire(this, 'text-changed', {value: this.text});
    }
    if (changedProperties.has('value')) {
      fire(this, 'value-changed', {value: this.value});
    }
  }

  override render() {
    return html`
      <paper-input
        .noLabelFloat=${true}
        id="input"
        class=${this.computeClass()}
        ?disabled=${this.disabled}
        .value=${this.text}
        @value-changed=${(e: CustomEvent) => {
          this.text = e.detail.value;
        }}
        .placeholder=${this.placeholder}
        @keydown=${this.handleKeydown}
        @focus=${this.onInputFocus}
        @blur=${this.onInputBlur}
        autocomplete="off"
        .label=${this.label}
      >
        <div slot="prefix">
          <slot name="prefix"></slot>
        </div>

        <div slot="suffix">
          <slot name="suffix"></slot>
        </div>
      </paper-input>
      <gr-autocomplete-dropdown
        .verticalOffset=${this.verticalOffset}
        id="suggestions"
        @item-selected=${this.handleItemSelect}
        @dropdown-closed=${this.focusWithoutDisplayingSuggestions}
        .suggestions=${this.suggestions}
        .queryStatus=${this.queryStatus}
        role="listbox"
        .index=${this.index}
      >
      </gr-autocomplete-dropdown>
    `;
  }

  get focusStart() {
    return this.input;
  }

  override focus() {
    this.nativeInput.focus();
  }

  private focusWithoutDisplayingSuggestions() {
    this.disableDisplayingSuggestions = true;
    this.focus();

    this.updateComplete.then(() => {
      this.disableDisplayingSuggestions = false;
    });
  }

  selectAll() {
    const nativeInputElement = this.nativeInput;
    if (!this.input?.value) {
      return;
    }
    nativeInputElement.setSelectionRange(0, this.input?.value.length);
  }

  clear() {
    this.text = '';
  }

  private handleItemSelectEnter(e: CustomEvent | KeyboardEvent) {
    this.handleInputCommit();
    e.stopPropagation();
    e.preventDefault();
    this.focusWithoutDisplayingSuggestions();
  }

  handleItemSelect(e: CustomEvent) {
    if (e.detail.trigger === 'click') {
      this.selected = e.detail.selected;
      this._commit();
      e.stopPropagation();
      e.preventDefault();
      this.focusWithoutDisplayingSuggestions();
    } else if (e.detail.trigger === 'enter') {
      this.handleItemSelectEnter(e);
    } else if (e.detail.trigger === 'tab') {
      if (this.tabComplete) {
        this.handleInputCommit(true);
        e.stopPropagation();
        e.preventDefault();
        this.focus();
      } else {
        this.setFocus(false);
      }
    }
  }

  /**
   * Set the text of the input without triggering the suggestion dropdown.
   *
   * @param text The new text for the input.
   */
  setText(text: string) {
    this.disableDisplayingSuggestions = true;
    this.text = text;

    this.updateComplete.then(() => {
      this.disableDisplayingSuggestions = false;
    });
  }

  onInputFocus() {
    this.setFocus(true);
    this.updateSuggestions();
    this.input?.classList.remove('warnUncommitted');
    // Needed so that --paper-input-container-input updated style is applied.
    this.requestUpdate();
  }

  onInputBlur() {
    this.input?.classList.toggle(
      'warnUncommitted',
      this.warnUncommitted && !!this.text.length && !this.focused
    );
    // Needed so that --paper-input-container-input updated style is applied.
    this.requestUpdate();
  }

  updateSuggestions() {
    if (this.text === undefined || this.threshold === undefined) return;

    // Reset suggestions for every update
    // This will also prevent from carrying over suggestions:
    // @see Issue 12039
    this.resetQueryOutput();

    // TODO(taoalpha): Also skip if text has not changed

    if (this.disableDisplayingSuggestions) {
      return;
    }

    if (!this.query) {
      return;
    }

    if (this.text.length < this.threshold) {
      this.value = '';
      return;
    }

    if (!this.focused) {
      return;
    }

    const queryId = GrAutocomplete.getNextQueryId();
    this.activeQueryId = queryId;
    this.setQueryStatus({
      type: AutocompleteQueryStatusType.LOADING,
      message: 'Loading...',
    });
    this.updateSuggestionsTask = debounce(
      this.updateSuggestionsTask,
      this.createUpdateTask(queryId, this.query, this.text),
      DEBOUNCE_WAIT_MS
    );
  }

  private createUpdateTask(
    queryId: number,
    query: AutocompleteQuery,
    text: string
  ): () => Promise<void> {
    return async () => {
      let suggestions: AutocompleteSuggestion[];
      try {
        suggestions = await query(text);
      } catch (e) {
        this.value = '';
        if (typeof e === 'string') {
          this.setQueryStatus({
            type: AutocompleteQueryStatusType.ERROR,
            message: e,
          });
        } else if (e instanceof Error) {
          this.setQueryStatus({
            type: AutocompleteQueryStatusType.ERROR,
            message: e.message,
          });
        }
        return;
      }
      if (queryId !== this.activeQueryId) {
        // Late response.
        return;
      }
      for (const suggestion of suggestions) {
        suggestion.text = suggestion?.name ?? '';
      }
      this.setSuggestions(suggestions);
      if (this.index === -1) {
        this.value = '';
      }
    };
  }

  setFocus(focused: boolean) {
    if (focused === this.focused) return;
    this.focused = focused;
    this.updateDropdownVisibility();
  }

  private shouldShowDropdown() {
    return (this.suggestions.length > 0 || this.queryStatus) && this.focused;
  }

  updateDropdownVisibility() {
    if (this.shouldShowDropdown()) {
      this.suggestionsDropdown?.open();
      return;
    }
    this.suggestionsDropdown?.close();
  }

  computeClass() {
    const classes = [];
    if (this.borderless) classes.push('borderless');
    if (this.showBlueFocusBorder) classes.push('showBlueFocusBorder');
    return classes.join(' ');
  }

  /**
   * handleKeydown used for key handling in the this.input?.
   */
  handleKeydown(e: KeyboardEvent) {
    this.setFocus(true);
    switch (e.key) {
      case 'ArrowUp':
        e.preventDefault();
        this.suggestionsDropdown?.cursorUp();
        break;
      case 'ArrowDown':
        e.preventDefault();
        this.suggestionsDropdown?.cursorDown();
        break;
      case 'Escape':
        e.preventDefault();
        this.cancel();
        break;
      case 'Tab':
        if (
          this.queryStatus?.type === AutocompleteQueryStatusType.LOADING &&
          this.tabComplete
        ) {
          e.preventDefault();
          // Queue tab on load.
          this.queryStatus = {
            type: AutocompleteQueryStatusType.LOADING,
            message: 'Loading... (Handle Tab on load)',
          };
          const queryId = this.activeQueryId;
          this.latestSuggestionUpdateComplete?.then(() => {
            if (queryId === this.activeQueryId) {
              this.handleInputCommit(/* _tabComplete=*/ true);
            }
          });
        } else if (this.suggestions.length > 0 && this.tabComplete) {
          e.preventDefault();
          this.handleInputCommit(/* _tabComplete=*/ true);
          this.focus();
        } else {
          this.setFocus(false);
        }
        break;
      case 'Enter':
        if (modifierPressed(e)) {
          break;
        }
        e.preventDefault();
        if (this.queryStatus?.type === AutocompleteQueryStatusType.LOADING) {
          // Queue enter on load.
          this.queryStatus = {
            type: AutocompleteQueryStatusType.LOADING,
            message: 'Loading... (Handle Enter on load)',
          };
          const queryId = this.activeQueryId;
          this.latestSuggestionUpdateComplete?.then(() => {
            if (queryId === this.activeQueryId) {
              this.handleItemSelectEnter(e);
            }
          });
        } else if (this.suggestions.length > 0) {
          // If suggestions are shown, act as if the keypress is in dropdown.
          // suggestions length is 0 if error is shown.
          this.handleItemSelectEnter(e);
        } else {
          this.handleInputCommit();
        }
        break;
      default:
        // For any normal keypress, return focus to the input to allow for
        // unbroken user input.
        this.focus();

        // Since this has been a normal keypress, the suggestions will have
        // been based on a previous input. Clear them. This prevents an
        // outdated suggestion from being used if the input keystroke is
        // immediately followed by a commit keystroke. @see Issue 8655
        this.resetQueryOutput();
        this.activeQueryId = 0;
    }
    this.dispatchEvent(
      new CustomEvent('input-keydown', {
        detail: {key: e.key, input: this.input},
        composed: true,
        bubbles: true,
      })
    );
  }

  cancel() {
    if (this.shouldShowDropdown()) {
      this.resetQueryOutput();
      // If query is in flight by setting id to 0 we indicate that the results
      // are outdated.
      this.activeQueryId = 0;
      this.requestUpdate();
    } else {
      fireEvent(this, 'cancel');
    }
  }

  handleInputCommit(_tabComplete?: boolean) {
    // Nothing to do if no suggestions.
    if (
      !this.allowNonSuggestedValues &&
      (this.suggestionsDropdown?.isHidden || this.suggestions.length === 0)
    ) {
      return;
    }

    this.selected = this.suggestionsDropdown?.getCursorTarget() ?? null;
    this._commit(_tabComplete);
  }

  updateValue(
    suggestion: HTMLElement | null,
    suggestions: AutocompleteSuggestion[]
  ) {
    if (!suggestion) {
      return;
    }
    const index = Number(suggestion.dataset['index']!);
    if (isNaN(index)) return;
    const completed = suggestions[index].value;
    if (completed === undefined || completed === null) return;
    if (this.multi) {
      // Append the completed text to the end of the string.
      // Allow spaces within quoted terms.
      const tokens = this.text.match(TOKENIZE_REGEX);
      if (tokens?.length) {
        tokens[tokens.length - 1] = completed;
        this.value = tokens.join(' ');
      }
    } else {
      this.value = completed;
    }
  }

  private readonly handleBodyClick = (e: Event) => {
    const eventPath = e.composedPath();
    if (!eventPath) return;
    for (let i = 0; i < eventPath.length; i++) {
      if (eventPath[i] === this) {
        return;
      }
    }
    this.setFocus(false);
    this.activeQueryId = 0;
  };

  /**
   * Commits the suggestion, optionally firing the commit event.
   *
   * @param silent Allows for silent committing of an
   * autocomplete suggestion in order to handle cases like tab-to-complete
   * without firing the commit event.
   */
  async _commit(silent?: boolean) {
    // Allow values that are not in suggestion list iff suggestions are empty.
    if (this.suggestions.length > 0) {
      this.updateValue(this.selected, this.suggestions);
    } else {
      this.value = this.text || '';
    }

    const value = this.value;

    // Value and text are mirrors of each other in multi mode.
    if (this.multi) {
      this.setText(this.value);
    } else {
      if (!this.clearOnCommit && this.selected) {
        const dataSet = this.selected.dataset;
        // index property cannot be null for the data-set
        if (dataSet) {
          const index = Number(dataSet['index']!);
          if (isNaN(index)) return;
          this.setText(this.suggestions[index]?.name || '');
        }
      } else {
        this.clear();
      }
    }

    this.resetQueryOutput();
    // we need willUpdate to send text-changed event before we can send the
    // 'commit' event
    await this.updateComplete;
    if (!silent) {
      this.dispatchEvent(
        new CustomEvent('commit', {
          detail: {value} as AutocompleteCommitEventDetail,
          composed: true,
          bubbles: true,
        })
      );
    }
  }

  // resetQueryOutput, setSuggestions and setQueryStatus insure that suggestions
  // and queryStatus are never set at the same time.
  private resetQueryOutput() {
    this.suggestions = [];
    this.queryStatus = undefined;
  }

  private setSuggestions(suggestions: AutocompleteSuggestion[]) {
    this.suggestions = suggestions;
    this.queryStatus = undefined;
  }

  private setQueryStatus(queryStatus: AutocompleteQueryStatus) {
    this.suggestions = [];
    this.queryStatus = queryStatus;
  }
}

/**
 * Often gr-autocomplete is used for BranchName, RepoName, etc...
 * GrTypedAutocomplete allows to define more precise typing in templates.
 * For example, instead of
 * $: {
 *   branchSelect: GrAutocomplete
 * }
 * you can write
 * $: {
 *   branchSelect: GrTypedAutocomplete<BranchName>
 * }
 * And later user $.branchSelect.text without type conversion to BranchName.
 */
export interface GrTypedAutocomplete<
  T extends PropertyType<GrAutocomplete, 'text'>
> extends GrAutocomplete {
  text: T;
  value: T;
  query?: AutocompleteQuery<T>;
}
