/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../gr-avatar/gr-avatar';
import '../gr-hovercard-account/gr-hovercard-account';
import '../gr-icon/gr-icon';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import '../../plugins/gr-endpoint-param/gr-endpoint-param';
import {getAppContext} from '../../../services/app-context';
import {getDisplayName} from '../../../utils/display-name-util';
import {
  isDetailedAccount,
  isSelf,
  isServiceUser,
} from '../../../utils/account-util';
import {ChangeInfo, AccountInfo, ServerInfo} from '../../../types/common';
import {hasOwnProperty} from '../../../utils/common-util';
import {fire} from '../../../utils/event-util';
import {isInvolved} from '../../../utils/change-util';
import {LitElement, css, html, TemplateResult} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
import {classMap} from 'lit/directives/class-map.js';
import {getRemovedByIconClickReason} from '../../../utils/attention-set-util';
import {ifDefined} from 'lit/directives/if-defined.js';
import {createSearchUrl} from '../../../models/views/search';
import {accountsModelToken} from '../../../models/accounts/accounts-model';
import {resolve} from '../../../models/dependency';
import {configModelToken} from '../../../models/config/config-model';
import {userModelToken} from '../../../models/user/user-model';
import {subscribe} from '../../lit/subscription-controller';

@customElement('gr-account-label')
export class GrAccountLabel extends LitElement {
  @property({type: Object})
  account?: AccountInfo;

  /**
   * Optional ChangeInfo object, typically comes from the change page or
   * from a row in a list of search results. This is needed for some change
   * related features like adding the user as a reviewer.
   */
  @property({type: Object})
  change?: ChangeInfo;

  /**
   * Should this user be considered to be in the attention set, regardless
   * of the current state of the change object?
   */
  @property({type: Boolean})
  forceAttention = false;

  /**
   * Only show the first name in the account label.
   */
  @property({type: Boolean})
  firstName = false;

  /**
   * Should attention set related features be shown in the component? Note
   * that the information whether the user is in the attention set or not is
   * part of the ChangeInfo object in the change property.
   */
  @property({type: Boolean})
  highlightAttention = false;

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

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

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

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

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

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

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

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

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

  // Private but used in tests.
  @state()
  selfAccount?: AccountInfo;

  // Private but used in tests.
  @state()
  config?: ServerInfo;

  readonly reporting = getAppContext().reportingService;

  private readonly restApiService = getAppContext().restApiService;

  private readonly getAccountsModel = resolve(this, accountsModelToken);

  private readonly getConfigModel = resolve(this, configModelToken);

  private readonly getUserModel = resolve(this, userModelToken);

  static override get styles() {
    return [
      css`
        :host {
          display: inline-block;
          vertical-align: top;
          position: relative;
          border-radius: var(--label-border-radius);
          box-sizing: border-box;
          white-space: nowrap;
          padding-left: var(--account-label-padding-left, 0);
        }
        :host([avatarShown]:not([attentionIconShown])) {
          padding-left: var(--account-label-circle-padding-left, 0);
        }
        :host([attentionIconShown]) {
          padding-left: var(--account-label-padding-left, 0);
        }
        .rightSidePadding {
          padding-right: var(--account-label-padding-right, 0);
          /* The existence of this element will also add 2(!) flexbox gaps */
          margin-left: -6px;
        }
        .container {
          display: flex;
          align-items: center;
          gap: 3px;
        }
        :host::after {
          content: var(--account-label-suffix);
        }
        :host([deselected][selectionChipStyle]) {
          background-color: var(--background-color-primary);
          border: 1px solid var(--comment-separator-color);
          border-radius: 8px;
          color: var(--deemphasized-text-color);
        }
        :host([selected][selectionChipStyle]) {
          background-color: var(--chip-selected-background-color);
          border: 1px solid var(--chip-selected-background-color);
          border-radius: 8px;
          color: var(--chip-selected-text-color);
        }
        :host([selected]) gr-icon.attention {
          color: var(--chip-selected-text-color);
        }
        gr-avatar {
          height: calc(var(--line-height-normal) - 2px);
          width: calc(var(--line-height-normal) - 2px);
        }
        .accountStatusDecorator,
        .hovercardTargetWrapper {
          display: contents;
        }
        #attentionButton {
          /* This negates the 4px horizontal padding, which we appreciate as a
         larger click target, but which we don't want to consume space. :-) */
          margin: 0 -4px 0 -4px;
          --gr-button-padding: 0 var(--spacing-xs);
          vertical-align: top;
        }
        gr-icon.attention {
          color: var(--deemphasized-text-color);
          transform: scaleX(0.8);
        }
        .name {
          display: inline-block;
          vertical-align: top;
          overflow: hidden;
          text-overflow: ellipsis;
          max-width: var(--account-max-length, 180px);
        }
        .hasAttention .name {
          font-weight: var(--font-weight-bold);
        }
        a.ownerLink {
          text-decoration: none;
          color: var(--primary-text-color);
          display: flex;
          align-items: center;
          gap: 3px;
        }
        :host([clickable]) a.ownerLink:hover .name {
          text-decoration: underline;
        }
      `,
    ];
  }

  override updated() {
    this.computeDetailedAccount();
  }

  private async computeDetailedAccount() {
    if (!this.account) return;
    // If this.account is already a detailed object, then there is no need to fill it.
    if (isDetailedAccount(this.account)) return;
    const account = await this.getAccountsModel().fillDetails(this.account);
    if (
      account &&
      // If we were not able to get a detailed object, then there is no point in updating the
      // account.
      isDetailedAccount(account) &&
      account !== this.account &&
      account._account_id === this.account._account_id
    ) {
      // AccountInfo returned by fillDetails has the email property set
      // to the primary email of the account. This poses a problem in
      // cases where a secondary email is used as the committer or author
      // email. Therefore, only fill in the *missing* properties.
      this.account = {...account, ...this.account};
    }
  }

  override render() {
    const {account, change, highlightAttention, forceAttention, config} = this;
    if (!account) return;
    this.attentionIconShown =
      forceAttention ||
      this.hasUnforcedAttention(highlightAttention, account, change);
    this.deselected = !this.selected;
    const hasAvatars = !!config?.plugin?.has_avatars;
    this.avatarShown = !this.hideAvatar && hasAvatars;

    return html`
      <div class="container">
        ${!this.hideHovercard
          ? html`<gr-hovercard-account
              for="hovercardTarget"
              .account=${account}
              .change=${change}
              .highlightAttention=${highlightAttention}
            ></gr-hovercard-account>`
          : ''}
        ${this.attentionIconShown
          ? html` <gr-tooltip-content
              ?has-tooltip=${this.computeAttentionButtonEnabled(
                highlightAttention,
                account,
                change,
                false,
                this.selfAccount
              )}
              title=${this.computeAttentionIconTitle(
                highlightAttention,
                account,
                change,
                forceAttention,
                this.selected,
                this.selfAccount
              )}
            >
              <gr-button
                id="attentionButton"
                link=""
                aria-label="Remove user from attention set"
                @click=${this.handleRemoveAttentionClick}
                ?disabled=${!this.computeAttentionButtonEnabled(
                  highlightAttention,
                  account,
                  change,
                  this.selected,
                  this.selfAccount
                )}
              >
                <div>
                  <gr-icon
                    icon="label_important"
                    filled
                    small
                    class="attention"
                  >
                  </gr-icon>
                </div>
              </gr-button>
            </gr-tooltip-content>`
          : ''}
        ${this.maybeRenderLink(html`
          <span
            class=${classMap({
              hovercardTargetWrapper: true,
              hasAttention: this.attentionIconShown,
            })}
          >
            ${this.avatarShown
              ? html`<gr-avatar .account=${account} imageSize="32"></gr-avatar>`
              : ''}
            <span
              tabindex=${this.hideHovercard ? '-1' : '0'}
              role=${ifDefined(this.hideHovercard ? undefined : 'button')}
              id="hovercardTarget"
              class="name"
              part="gr-account-label-text"
            >
              ${this.computeName(account, this.firstName, this.config)}
            </span>
            ${this.renderAccountStatusPlugins()}
          </span>
        `)}
      </div>
    `;
  }

  constructor() {
    super();
    subscribe(
      this,
      () => this.getConfigModel().serverConfig$,
      x => (this.config = x)
    );
    subscribe(
      this,
      () => this.getUserModel().account$,
      x => (this.selfAccount = x)
    );
    this.addEventListener('attention-set-updated', () => {
      // For re-evaluation of everything that depends on 'change'.
      if (this.change) this.change = {...this.change};
    });
  }

  private maybeRenderLink(span: TemplateResult) {
    if (!this.clickable || !this.account) return span;
    const url = createSearchUrl({
      owner:
        this.account.email ||
        this.account.username ||
        this.account.name ||
        `${this.account._account_id}`,
    });
    if (!url) return span;
    return html`<a class="ownerLink" href=${url} tabindex="-1">${span}</a>`;
  }

  private renderAccountStatusPlugins() {
    if (!this.account?._account_id || this.noStatusIcons) {
      return;
    }
    return html`
      <gr-endpoint-decorator
        class="accountStatusDecorator"
        name="account-status-icon"
      >
        <gr-endpoint-param
          name="accountId"
          .value=${this.account._account_id}
        ></gr-endpoint-param>
        <span class="rightSidePadding"></span>
      </gr-endpoint-decorator>
    `;
  }

  private isAttentionSetEnabled(
    highlight: boolean,
    account: AccountInfo,
    change?: ChangeInfo
  ) {
    return highlight && !!change && !!account && !isServiceUser(account);
  }

  private hasUnforcedAttention(
    highlight: boolean,
    account: AccountInfo,
    change?: ChangeInfo
  ): boolean {
    return !!(
      this.isAttentionSetEnabled(highlight, account, change) &&
      change &&
      change.attention_set &&
      !!account._account_id &&
      hasOwnProperty(change.attention_set, account._account_id)
    );
  }

  // Private but used in tests.
  computeName(account?: AccountInfo, firstName?: boolean, config?: ServerInfo) {
    return getDisplayName(config, account, firstName);
  }

  private handleRemoveAttentionClick(e: MouseEvent) {
    if (!this.account || !this.change) return;
    if (this.selected) return;
    e.preventDefault();
    e.stopPropagation();
    if (!this.account._account_id) return;

    fire(this, 'show-alert', {
      message: 'Saving attention set update ...',
      dismissOnNavigation: true,
    });

    // We are deliberately updating the UI before making the API call. It is a
    // risk that we are taking to achieve a better UX for 99.9% of the cases.
    const reason = getRemovedByIconClickReason(this.selfAccount, this.config);
    if (this.change.attention_set)
      delete this.change.attention_set[this.account._account_id];
    // For re-evaluation of everything that depends on 'change'.
    this.change = {...this.change};

    this.reporting.reportInteraction(
      'attention-icon-remove',
      this.reportingDetails()
    );
    this.restApiService
      .removeFromAttentionSet(
        this.change._number,
        this.account._account_id,
        reason
      )
      .then(() => {
        fire(this, 'hide-alert', {});
      });
  }

  private reportingDetails() {
    if (!this.account) return;
    const targetId = this.account._account_id;
    const ownerId =
      (this.change && this.change.owner && this.change.owner._account_id) || -1;
    const selfId = this.selfAccount?._account_id || -1;
    const reviewers =
      this.change && this.change.reviewers && this.change.reviewers.REVIEWER
        ? [...this.change.reviewers.REVIEWER]
        : [];
    const reviewerIds = reviewers
      .map(r => r._account_id)
      .filter(rId => rId !== ownerId);
    return {
      actionByOwner: selfId === ownerId,
      actionByReviewer: selfId !== -1 && reviewerIds.includes(selfId),
      targetIsOwner: targetId === ownerId,
      targetIsReviewer: reviewerIds.includes(targetId),
      targetIsSelf: targetId === selfId,
    };
  }

  private computeAttentionButtonEnabled(
    highlight: boolean,
    account: AccountInfo,
    change: ChangeInfo | undefined,
    selected: boolean,
    selfAccount?: AccountInfo
  ) {
    if (selected) return true;
    return (
      !!this.hasUnforcedAttention(highlight, account, change) &&
      (isInvolved(change, selfAccount) || isSelf(account, selfAccount))
    );
  }

  private computeAttentionIconTitle(
    highlight: boolean,
    account: AccountInfo,
    change: ChangeInfo | undefined,
    force: boolean,
    selected: boolean,
    selfAccount?: AccountInfo
  ) {
    const enabled = this.computeAttentionButtonEnabled(
      highlight,
      account,
      change,
      selected,
      selfAccount
    );
    const removeFromASTooltip = `Click to remove ${
      account._account_id === selfAccount?._account_id ? 'yourself' : 'the user'
    } from the attention set`;
    return enabled
      ? removeFromASTooltip
      : force
      ? 'Disabled. Use "Modify" to make changes.'
      : 'Disabled. Only involved users can change.';
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-account-label': GrAccountLabel;
  }
}
