/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '@polymer/iron-input/iron-input';
import '../../shared/gr-button/gr-button';
import {EmailInfo} from '../../../types/common';
import {getAppContext} from '../../../services/app-context';
import {LitElement, css, html} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
import {sharedStyles} from '../../../styles/shared-styles';
import {formStyles} from '../../../styles/gr-form-styles';
import {ValueChangedEvent} from '../../../types/events';
import {fire} from '../../../utils/event-util';

@customElement('gr-email-editor')
export class GrEmailEditor extends LitElement {
  @property({type: Boolean}) hasUnsavedChanges = false;

  /* private but used in test */
  @state() emails: EmailInfo[] = [];

  /* private but used in test */
  @state() emailsToRemove: EmailInfo[] = [];

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

  readonly restApiService = getAppContext().restApiService;

  static override styles = [
    sharedStyles,
    formStyles,
    css`
      th {
        color: var(--deemphasized-text-color);
        text-align: left;
      }
      #emailTable .emailColumn {
        min-width: 32.5em;
        width: auto;
      }
      #emailTable .preferredHeader {
        text-align: center;
        width: 6em;
      }
      #emailTable .preferredControl {
        cursor: pointer;
        height: auto;
        text-align: center;
      }
      #emailTable .preferredControl .preferredRadio {
        height: auto;
      }
      .preferredControl:hover {
        outline: 1px solid var(--border-color);
      }
    `,
  ];

  override render() {
    return html`<div class="gr-form-styles">
      <table id="emailTable">
        <thead>
          <tr>
            <th class="emailColumn">Email</th>
            <th class="preferredHeader">Preferred</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          ${this.emails.map((email, index) => this.renderEmail(email, index))}
        </tbody>
      </table>
    </div>`;
  }

  private renderEmail(email: EmailInfo, index: number) {
    return html`<tr>
      <td class="emailColumn">${email.email}</td>
      <td class="preferredControl" @click=${this.handlePreferredControlClick}>
        <iron-input
          class="preferredRadio"
          @change=${this.handlePreferredChange}
          .bindValue=${email.email}
        >
          <input
            class="preferredRadio"
            type="radio"
            @change=${this.handlePreferredChange}
            name="preferred"
            ?checked=${email.preferred}
          />
        </iron-input>
      </td>
      <td>
        <gr-button
          data-index=${index}
          @click=${this.handleDeleteButton}
          ?disabled=${this.checkPreferred(email.preferred)}
          class="remove-button"
          >Delete</gr-button
        >
      </td>
    </tr>`;
  }

  loadData() {
    return this.restApiService.getAccountEmails().then(emails => {
      this.emails = emails ?? [];
    });
  }

  save() {
    const promises: Promise<unknown>[] = [];

    for (const emailObj of this.emailsToRemove) {
      promises.push(this.restApiService.deleteAccountEmail(emailObj.email));
    }

    if (this.newPreferred) {
      promises.push(
        this.restApiService.setPreferredAccountEmail(this.newPreferred)
      );
    }

    return Promise.all(promises).then(() => {
      this.emailsToRemove = [];
      this.newPreferred = '';
      this.setHasUnsavedChanges(false);
    });
  }

  private handleDeleteButton(e: Event) {
    const target = e.target;
    if (!(target instanceof Element)) return;
    const indexStr = target.getAttribute('data-index');
    if (indexStr === null) return;
    const index = Number(indexStr);
    const email = this.emails[index];
    this.emailsToRemove = [...this.emailsToRemove, email];
    this.emails.splice(index, 1);
    this.requestUpdate();
    this.setHasUnsavedChanges(true);
  }

  private handlePreferredControlClick(e: Event) {
    if (
      e.target instanceof HTMLElement &&
      e.target.classList.contains('preferredControl') &&
      e.target.firstElementChild instanceof HTMLInputElement
    ) {
      e.target.firstElementChild.click();
    }
  }

  private handlePreferredChange(e: Event) {
    if (!(e.target instanceof HTMLInputElement)) return;
    const preferred = e.target.value;
    for (let i = 0; i < this.emails.length; i++) {
      if (preferred === this.emails[i].email) {
        this.emails[i].preferred = true;
        this.requestUpdate();
        this.newPreferred = preferred;
        this.setHasUnsavedChanges(true);
      } else if (this.emails[i].preferred) {
        this.emails[i].preferred = false;
        this.requestUpdate();
      }
    }
  }

  private checkPreferred(preferred?: boolean) {
    return preferred ?? false;
  }

  private setHasUnsavedChanges(value: boolean) {
    this.hasUnsavedChanges = value;
    fire(this, 'has-unsaved-changes-changed', {value});
  }
}

declare global {
  interface HTMLElementEventMap {
    'has-unsaved-changes-changed': ValueChangedEvent<boolean>;
  }
  interface HTMLElementTagNameMap {
    'gr-email-editor': GrEmailEditor;
  }
}
