/**
 * @license
 * Copyright (C) 2018 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 '../../../styles/gr-font-styles';
import '../../../styles/gr-voting-styles';
import '../../../styles/shared-styles';
import '../gr-vote-chip/gr-vote-chip';
import '../gr-account-label/gr-account-label';
import '../gr-account-chip/gr-account-chip';
import '../gr-button/gr-button';
import '../gr-icons/gr-icons';
import '../gr-label/gr-label';
import '../gr-tooltip-content/gr-tooltip-content';
import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
import {
  AccountInfo,
  LabelInfo,
  ApprovalInfo,
  AccountId,
  isQuickLabelInfo,
  isDetailedLabelInfo,
  LabelNameToInfoMap,
} from '../../../types/common';
import {LitElement, css, html} from 'lit';
import {customElement, property} from 'lit/decorators';
import {GrButton} from '../gr-button/gr-button';
import {
  canVote,
  getApprovalInfo,
  getVotingRangeOrDefault,
  hasNeutralStatus,
  hasVoted,
  showNewSubmitRequirements,
  valueString,
} from '../../../utils/label-util';
import {getAppContext} from '../../../services/app-context';
import {ParsedChangeInfo} from '../../../types/types';
import {fontStyles} from '../../../styles/gr-font-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {votingStyles} from '../../../styles/gr-voting-styles';
import {ifDefined} from 'lit/directives/if-defined';
import {fireReload} from '../../../utils/event-util';
import {sortReviewers} from '../../../utils/attention-set-util';

declare global {
  interface HTMLElementTagNameMap {
    'gr-label-info': GrLabelInfo;
  }
}

enum LabelClassName {
  NEGATIVE = 'negative',
  POSITIVE = 'positive',
  MIN = 'min',
  MAX = 'max',
}

interface FormattedLabel {
  className?: LabelClassName;
  account: ApprovalInfo | AccountInfo;
  value: string;
}

@customElement('gr-label-info')
export class GrLabelInfo extends LitElement {
  @property({type: Object})
  labelInfo?: LabelInfo;

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

  @property({type: Object})
  change?: ParsedChangeInfo;

  @property({type: Object})
  account?: AccountInfo;

  /**
   * A user is able to delete a vote iff the mutable property is true and the
   * reviewer that left the vote exists in the list of removable_reviewers
   * received from the backend.
   */
  @property({type: Boolean})
  mutable = false;

  /**
   * if true - show all reviewers that can vote on label
   * if false - show only reviewers that voted on label
   */
  @property({type: Boolean})
  showAllReviewers = true;

  private readonly restApiService = getAppContext().restApiService;

  private readonly reporting = getAppContext().reportingService;

  private readonly flagsService = getAppContext().flagsService;

  // TODO(TS): not used, remove later
  _xhrPromise?: Promise<void>;

  static override get styles() {
    return [
      sharedStyles,
      fontStyles,
      votingStyles,
      css`
        .placeholder {
          color: var(--deemphasized-text-color);
        }
        .hidden {
          display: none;
        }
        /* Note that most of the .voteChip styles are coming from the
         gr-voting-styles include. */
        .voteChip {
          display: flex;
          justify-content: center;
          margin-right: var(--spacing-s);
          padding: 1px;
        }
        .max {
          background-color: var(--vote-color-approved);
        }
        .min {
          background-color: var(--vote-color-rejected);
        }
        .positive {
          background-color: var(--vote-color-recommended);
          border-radius: 12px;
          border: 1px solid var(--vote-outline-recommended);
          color: var(--chip-color);
        }
        .negative {
          background-color: var(--vote-color-disliked);
          border-radius: 12px;
          border: 1px solid var(--vote-outline-disliked);
          color: var(--chip-color);
        }
        .hidden {
          display: none;
        }
        td {
          vertical-align: top;
        }
        tr {
          min-height: var(--line-height-normal);
        }
        gr-tooltip-content {
          display: block;
        }
        gr-button {
          vertical-align: top;
        }
        gr-button::part(paper-button) {
          height: var(--line-height-normal);
          width: var(--line-height-normal);
          padding: 0;
        }
        gr-button[disabled] iron-icon {
          color: var(--border-color);
        }
        gr-account-label {
          --account-max-length: 100px;
          margin-right: var(--spacing-xs);
        }
        iron-icon {
          height: calc(var(--line-height-normal) - 2px);
          width: calc(var(--line-height-normal) - 2px);
        }
        .labelValueContainer:not(:first-of-type) td {
          padding-top: var(--spacing-s);
        }
        .reviewer-row {
          padding-top: var(--spacing-s);
        }
        .reviewer-row:first-of-type {
          padding-top: 0;
        }
        .reviewer-row gr-account-chip,
        .reviewer-row gr-tooltip-content {
          display: inline-block;
          vertical-align: top;
        }
        .reviewer-row .no-votes {
          color: var(--deemphasized-text-color);
          margin-left: var(--spacing-xs);
        }
        gr-vote-chip {
          --gr-vote-chip-width: 14px;
          --gr-vote-chip-height: 14px;
        }
      `,
    ];
  }

  override render() {
    if (showNewSubmitRequirements(this.flagsService, this.change)) {
      return this.renderNewSubmitRequirements();
    } else {
      return this.renderOldSubmitRequirements();
    }
  }

  private renderNewSubmitRequirements() {
    const labelInfo = this.labelInfo;
    if (!labelInfo) return;
    const reviewers = (this.change?.reviewers['REVIEWER'] ?? [])
      .filter(reviewer => {
        if (this.showAllReviewers) {
          if (isDetailedLabelInfo(labelInfo)) {
            return canVote(labelInfo, reviewer);
          } else {
            // isQuickLabelInfo
            return hasVoted(labelInfo, reviewer);
          }
        } else {
          // !showAllReviewers
          return hasVoted(labelInfo, reviewer);
        }
      })
      .sort((r1, r2) => sortReviewers(r1, r2, this.change, this.account));
    return html`<div>
      ${reviewers.map(reviewer => this.renderReviewerVote(reviewer))}
    </div>`;
  }

  private renderOldSubmitRequirements() {
    const labelInfo = this.labelInfo;
    return html` <p
        class="placeholder ${this.computeShowPlaceholder(
          labelInfo,
          this.change?.labels
        )}"
      >
        No votes
      </p>
      <table>
        ${this.mapLabelInfo(labelInfo, this.account, this.change?.labels).map(
          mappedLabel => this.renderLabel(mappedLabel)
        )}
      </table>`;
  }

  renderReviewerVote(reviewer: AccountInfo) {
    const labelInfo = this.labelInfo;
    if (!labelInfo) return;
    const approvalInfo = isDetailedLabelInfo(labelInfo)
      ? getApprovalInfo(labelInfo, reviewer)
      : undefined;
    const noVoteYet =
      !hasVoted(labelInfo, reviewer) ||
      (isDetailedLabelInfo(labelInfo) &&
        hasNeutralStatus(labelInfo, approvalInfo));
    return html`<div class="reviewer-row">
      <gr-account-chip
        .account=${reviewer}
        .change=${this.change}
        .vote=${approvalInfo}
        .label=${labelInfo}
      >
        <gr-vote-chip
          slot="vote-chip"
          .vote=${approvalInfo}
          .label=${labelInfo}
          circle-shape
        ></gr-vote-chip
      ></gr-account-chip>
      ${noVoteYet
        ? this.renderVoteAbility(reviewer)
        : html`${this.renderRemoveVote(reviewer)}`}
    </div>`;
  }

  renderLabel(mappedLabel: FormattedLabel) {
    const {labelInfo, change} = this;
    return html` <tr class="labelValueContainer">
      <td>
        <gr-tooltip-content
          has-tooltip
          title=${this._computeValueTooltip(labelInfo, mappedLabel.value)}
        >
          <gr-label class="${mappedLabel.className} voteChip font-small">
            ${mappedLabel.value}
          </gr-label>
        </gr-tooltip-content>
      </td>
      <td>
        <gr-account-label
          clickable
          .account=${mappedLabel.account}
          .change=${change}
        ></gr-account-label>
      </td>
      <td>${this.renderRemoveVote(mappedLabel.account)}</td>
    </tr>`;
  }

  private renderVoteAbility(reviewer: AccountInfo) {
    if (this.labelInfo && isDetailedLabelInfo(this.labelInfo)) {
      const approvalInfo = getApprovalInfo(this.labelInfo, reviewer);
      if (approvalInfo?.permitted_voting_range) {
        const {min, max} = approvalInfo?.permitted_voting_range;
        return html`<span class="no-votes"
          >Can vote ${valueString(min)}/${valueString(max)}</span
        >`;
      }
    }
    return html`<span class="no-votes">No votes</span>`;
  }

  private renderRemoveVote(reviewer: AccountInfo) {
    return html`<gr-tooltip-content has-tooltip title="Remove vote">
      <gr-button
        link
        aria-label="Remove vote"
        @click=${this.onDeleteVote}
        data-account-id=${ifDefined(reviewer._account_id as number | undefined)}
        class="deleteBtn ${this.computeDeleteClass(
          reviewer,
          this.mutable,
          this.change
        )}"
      >
        <iron-icon icon="gr-icons:delete"></iron-icon>
      </gr-button>
    </gr-tooltip-content>`;
  }

  /**
   * This method also listens on change.labels.*,
   * to trigger computation when a label is removed from the change.
   *
   * The third parameter is just for *triggering* computation.
   */
  private mapLabelInfo(
    labelInfo?: LabelInfo,
    account?: AccountInfo,
    _?: LabelNameToInfoMap
  ): FormattedLabel[] {
    const result: FormattedLabel[] = [];
    if (!labelInfo) {
      return result;
    }
    if (!isDetailedLabelInfo(labelInfo)) {
      if (
        isQuickLabelInfo(labelInfo) &&
        (labelInfo.rejected || labelInfo.approved)
      ) {
        const ok = labelInfo.approved || !labelInfo.rejected;
        return [
          {
            value: ok ? '👍️' : '👎️',
            className: ok ? LabelClassName.POSITIVE : LabelClassName.NEGATIVE,
            // executed only if approved or rejected is not undefined
            account: ok ? labelInfo.approved! : labelInfo.rejected!,
          },
        ];
      }
      return result;
    }

    // Sort votes by positivity.
    // TODO(TS): maybe mark value as required if always present
    const votes = (labelInfo.all || []).sort(
      (a, b) => (a.value || 0) - (b.value || 0)
    );
    const votingRange = getVotingRangeOrDefault(labelInfo);
    for (const label of votes) {
      if (
        label.value &&
        (!isQuickLabelInfo(labelInfo) ||
          label.value !== labelInfo.default_value)
      ) {
        let labelClassName;
        let labelValPrefix = '';
        if (label.value > 0) {
          labelValPrefix = '+';
          if (label.value === votingRange.max) {
            labelClassName = LabelClassName.MAX;
          } else {
            labelClassName = LabelClassName.POSITIVE;
          }
        } else if (label.value < 0) {
          if (label.value === votingRange.min) {
            labelClassName = LabelClassName.MIN;
          } else {
            labelClassName = LabelClassName.NEGATIVE;
          }
        }
        const formattedLabel: FormattedLabel = {
          value: `${labelValPrefix}${label.value}`,
          className: labelClassName,
          account: label,
        };
        if (label._account_id === account?._account_id) {
          // Put self-votes at the top.
          result.unshift(formattedLabel);
        } else {
          result.push(formattedLabel);
        }
      }
    }
    return result;
  }

  /**
   * A user is able to delete a vote iff the mutable property is true and the
   * reviewer that left the vote exists in the list of removable_reviewers
   * received from the backend.
   *
   * @param reviewer An object describing the reviewer that left the
   *     vote.
   */
  private computeDeleteClass(
    reviewer: ApprovalInfo,
    mutable: boolean,
    change?: ParsedChangeInfo
  ) {
    if (!mutable || !change || !change.removable_reviewers) {
      return 'hidden';
    }
    const removable = change.removable_reviewers;
    if (removable.find(r => r._account_id === reviewer?._account_id)) {
      return '';
    }
    return 'hidden';
  }

  /**
   * Closure annotation for Polymer.prototype.splice is off.
   * For now, suppressing annotations.
   */
  private onDeleteVote(e: MouseEvent) {
    if (!this.change) return;

    e.preventDefault();
    let target = (dom(e) as EventApi).rootTarget as GrButton;
    while (!target.classList.contains('deleteBtn')) {
      if (!target.parentElement) {
        return;
      }
      target = target.parentElement as GrButton;
    }

    target.disabled = true;
    const accountID = Number(
      `${target.getAttribute('data-account-id')}`
    ) as AccountId;
    this._xhrPromise = this.restApiService
      .deleteVote(this.change._number, accountID, this.label)
      .then(response => {
        target.disabled = false;
        if (!response.ok) {
          return;
        }
        if (this.change) {
          fireReload(this);
        }
      })
      .catch(err => {
        this.reporting.error(err);
        target.disabled = false;
        return;
      });
  }

  _computeValueTooltip(labelInfo: LabelInfo | undefined, score: string) {
    if (
      !labelInfo ||
      !isDetailedLabelInfo(labelInfo) ||
      !labelInfo.values?.[score]
    ) {
      return '';
    }
    return labelInfo.values[score];
  }

  /**
   * This method also listens change.labels.* in
   * order to trigger computation when a label is removed from the change.
   *
   * The second parameter is just for *triggering* computation.
   */
  private computeShowPlaceholder(
    labelInfo?: LabelInfo,
    _?: LabelNameToInfoMap
  ) {
    if (!labelInfo) {
      return '';
    }
    if (
      !isDetailedLabelInfo(labelInfo) &&
      isQuickLabelInfo(labelInfo) &&
      (labelInfo.rejected || labelInfo.approved)
    ) {
      return 'hidden';
    }

    if (isDetailedLabelInfo(labelInfo) && labelInfo.all) {
      for (const label of labelInfo.all) {
        if (
          label.value &&
          (!isQuickLabelInfo(labelInfo) ||
            label.value !== labelInfo.default_value)
        ) {
          return 'hidden';
        }
      }
    }
    return '';
  }
}
