/**
 * @license
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import '@polymer/iron-dropdown/iron-dropdown';
import '@polymer/paper-input/paper-input';
import '../../../styles/shared-styles';
import '../gr-button/gr-button';
import '../../shared/gr-autocomplete/gr-autocomplete';
import {IronDropdownElement} from '@polymer/iron-dropdown/iron-dropdown';
import {PaperInputElementExt} from '../../../types/types';
import {
  AutocompleteQuery,
  GrAutocomplete,
} from '../gr-autocomplete/gr-autocomplete';
import {addShortcut, Key} from '../../../utils/dom-util';
import {queryAndAssert} from '../../../utils/common-util';
import {LitElement, css, html} from 'lit';
import {customElement, property, query, state} from 'lit/decorators';
import {sharedStyles} from '../../../styles/shared-styles';

const AWAIT_MAX_ITERS = 10;
const AWAIT_STEP = 5;

declare global {
  interface HTMLElementTagNameMap {
    'gr-editable-label': GrEditableLabel;
  }
}

@customElement('gr-editable-label')
export class GrEditableLabel extends LitElement {
  /**
   * Fired when the value is changed.
   *
   * @event changed
   */

  @query('#dropdown')
  dropdown?: IronDropdownElement;

  @property()
  labelText = '';

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

  @property()
  value?: string;

  @property()
  placeholder = '';

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

  @property({type: Boolean, reflect: true})
  uppercase = false;

  @property({type: Number})
  maxLength?: number;

  /* private but used in test */
  @state() inputText = '';

  // This is used to push the iron-input element up on the page, so
  // the input is placed in approximately the same position as the
  // trigger.
  @state() readonly verticalOffset = -30;

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

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

  @property({type: Object})
  query: AutocompleteQuery = () => Promise.resolve([]);

  static override get styles() {
    return [
      sharedStyles,
      css`
        :host {
          align-items: center;
          display: inline-flex;
        }
        :host([uppercase]) label {
          text-transform: uppercase;
        }
        input,
        label {
          width: 100%;
        }
        label {
          color: var(--deemphasized-text-color);
          display: inline-block;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
        label.editable {
          color: var(--link-color);
          cursor: pointer;
        }
        #dropdown {
          box-shadow: var(--elevation-level-2);
        }
        .inputContainer {
          background-color: var(--dialog-background-color);
          padding: var(--spacing-m);
        }
        .buttons {
          display: flex;
          justify-content: flex-end;
          padding-top: var(--spacing-l);
          width: 100%;
        }
        .buttons gr-button {
          margin-left: var(--spacing-m);
        }
        paper-input {
          --paper-input-container: {
            padding: 0;
            min-width: 15em;
          }
          --paper-input-container-input: {
            font-size: inherit;
          }
          --paper-input-container-focus-color: var(--link-color);
        }
        gr-button iron-icon {
          color: inherit;
          --iron-icon-height: 18px;
          --iron-icon-width: 18px;
        }
        gr-button.pencil {
          --gr-button-padding: 0px 0px;
        }
      `,
    ];
  }

  override render() {
    this.setAttribute('title', this.computeLabel());
    return html`${this.renderActivateButton()}
      <iron-dropdown
        id="dropdown"
        .verticalAlign=${'auto'}
        .horizontalAlign=${'auto'}
        .verticalOffset=${this.verticalOffset}
        allowOutsideScroll
        @iron-overlay-canceled=${this.cancel}
      >
        <div class="dropdown-content" slot="dropdown-content">
          <div class="inputContainer" part="input-container">
            ${this.renderInputBox()}
            <div class="buttons">
              <gr-button link="" id="cancelBtn" @click=${this.cancel}
                >cancel</gr-button
              >
              <gr-button link="" id="saveBtn" @click=${this.save}
                >save</gr-button
              >
            </div>
          </div>
        </div>
      </iron-dropdown>`;
  }

  private renderActivateButton() {
    if (this.showAsEditPencil) {
      return html`<gr-button
        link=""
        class="pencil ${this.computeLabelClass()}"
        @click=${this.showDropdown}
        title=${this.computeLabel()}
        ><iron-icon icon="gr-icons:edit"></iron-icon
      ></gr-button>`;
    } else {
      return html`<label
        class=${this.computeLabelClass()}
        title=${this.computeLabel()}
        aria-label=${this.computeLabel()}
        @click=${this.showDropdown}
        part="label"
        >${this.computeLabel()}</label
      >`;
    }
  }

  private renderInputBox() {
    if (this.autocomplete) {
      return html`<gr-autocomplete
        .label=${this.labelText}
        id="autocomplete"
        .text=${this.inputText}
        .query=${this.query}
        @commit=${this.handleCommit}
        @text-changed=${(e: CustomEvent) => {
          this.inputText = e.detail.value;
        }}
      >
      </gr-autocomplete>`;
    } else {
      return html`<paper-input
        id="input"
        .label=${this.labelText}
        .maxlength=${this.maxLength}
        .value=${this.inputText}
      ></paper-input>`;
    }
  }

  /** Called in disconnectedCallback. */
  private cleanups: (() => void)[] = [];

  override disconnectedCallback() {
    super.disconnectedCallback();
    for (const cleanup of this.cleanups) cleanup();
    this.cleanups = [];
  }

  override connectedCallback() {
    super.connectedCallback();
    if (!this.getAttribute('tabindex')) {
      this.setAttribute('tabindex', '0');
    }
    if (!this.getAttribute('id')) {
      this.setAttribute('id', 'global');
    }
    this.cleanups.push(
      addShortcut(this, {key: Key.ENTER}, e => this.handleEnter(e))
    );
    this.cleanups.push(
      addShortcut(this, {key: Key.ESC}, e => this.handleEsc(e))
    );
  }

  private usePlaceholder(value?: string, placeholder?: string) {
    return (!value || !value.length) && placeholder;
  }

  private computeLabel(): string {
    const {value, placeholder} = this;
    if (this.usePlaceholder(value, placeholder)) {
      return placeholder;
    }
    return value || '';
  }

  private showDropdown() {
    if (this.readOnly || this.editing) return;
    return this.openDropdown().then(() => {
      this.nativeInput.focus();
      const input = this.getInput();
      if (!input?.value) return;
      this.nativeInput.setSelectionRange(0, input.value.length);
    });
  }

  open() {
    return this.openDropdown().then(() => {
      this.nativeInput.focus();
    });
  }

  private openDropdown() {
    this.dropdown?.open();
    this.inputText = this.value || '';
    this.editing = true;

    return new Promise<void>(resolve => {
      this.awaitOpen(resolve);
    });
  }

  /**
   * NOTE: (wyatta) Slightly hacky way to listen to the overlay actually
   * opening. Eventually replace with a direct way to listen to the overlay.
   */
  private awaitOpen(fn: () => void) {
    let iters = 0;
    const step = () => {
      setTimeout(() => {
        if (this.dropdown?.style.display !== 'none') {
          fn.call(this);
        } else if (iters++ < AWAIT_MAX_ITERS) {
          step.call(this);
        }
      }, AWAIT_STEP);
    };
    step.call(this);
  }

  private save() {
    if (!this.editing) {
      return;
    }
    this.dropdown?.close();
    const input = this.getInput();
    if (input) {
      this.value = input.value ?? undefined;
    } else {
      this.value = this.inputText || '';
    }
    this.editing = false;
    this.dispatchEvent(
      new CustomEvent('changed', {
        detail: this.value,
        composed: true,
        bubbles: true,
      })
    );
  }

  private cancel() {
    if (!this.editing) {
      return;
    }
    this.dropdown?.close();
    this.editing = false;
    this.inputText = this.value || '';
  }

  private get nativeInput(): HTMLInputElement {
    return (this.getInput()?.$.nativeInput ||
      this.getInput()?.inputElement ||
      this.getGrAutocomplete()) as HTMLInputElement;
  }

  private handleEnter(event: KeyboardEvent) {
    const grAutocomplete = this.getGrAutocomplete();
    if (event.composedPath().some(el => el === grAutocomplete)) {
      return;
    }
    const inputContainer = queryAndAssert(this, '.inputContainer');
    const isEventFromInput = event
      .composedPath()
      .some(element => element === inputContainer);
    if (isEventFromInput) {
      this.save();
    }
  }

  private handleEsc(event: KeyboardEvent) {
    const inputContainer = queryAndAssert(this, '.inputContainer');
    const isEventFromInput = event
      .composedPath()
      .some(element => element === inputContainer);
    if (isEventFromInput) {
      this.cancel();
    }
  }

  private handleCommit() {
    this.getInput()?.focus();
  }

  private computeLabelClass() {
    const {readOnly, value, placeholder} = this;
    const classes = [];
    if (!readOnly) {
      classes.push('editable');
    }
    if (this.usePlaceholder(value, placeholder)) {
      classes.push('placeholder');
    }
    return classes.join(' ');
  }

  getInput(): PaperInputElementExt | null {
    return this.shadowRoot!.querySelector<PaperInputElementExt>('#input');
  }

  getGrAutocomplete(): GrAutocomplete | null {
    return this.shadowRoot!.querySelector<GrAutocomplete>('#autocomplete');
  }
}
