/**
 * @license
 * Copyright (C) 2021 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 '../../shared/gr-label-info/gr-label-info';
import '../gr-submit-requirement-hovercard/gr-submit-requirement-hovercard';
import '../gr-trigger-vote/gr-trigger-vote';
import '../gr-change-summary/gr-change-summary';
import '../../shared/gr-limited-text/gr-limited-text';
import '../../shared/gr-vote-chip/gr-vote-chip';
import {LitElement, css, html, TemplateResult} from 'lit';
import {customElement, property, state} from 'lit/decorators';
import {ParsedChangeInfo} from '../../../types/types';
import {
  AccountInfo,
  isDetailedLabelInfo,
  isQuickLabelInfo,
  LabelNameToInfoMap,
  SubmitRequirementResultInfo,
  SubmitRequirementStatus,
} from '../../../api/rest-api';
import {
  extractAssociatedLabels,
  getAllUniqueApprovals,
  getRequirements,
  getTriggerVotes,
  hasNeutralStatus,
  hasVotes,
  iconForStatus,
  orderSubmitRequirements,
} from '../../../utils/label-util';
import {fontStyles} from '../../../styles/gr-font-styles';
import {capitalizeFirstLetter, charsOnly} from '../../../utils/string-util';
import {subscribe} from '../../lit/subscription-controller';
import {CheckRun} from '../../../models/checks/checks-model';
import {getResultsOf, hasResultsOf} from '../../../models/checks/checks-util';
import {Category} from '../../../api/checks';
import {fireShowPrimaryTab} from '../../../utils/event-util';
import {PrimaryTab} from '../../../constants/constants';
import {submitRequirementsStyles} from '../../../styles/gr-submit-requirements-styles';
import {resolve} from '../../../models/dependency';
import {checksModelToken} from '../../../models/checks/checks-model';

/**
 * @attr {Boolean} suppress-title - hide titles, currently for hovercard view
 */
@customElement('gr-submit-requirements')
export class GrSubmitRequirements extends LitElement {
  @property({type: Object})
  change?: ParsedChangeInfo;

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

  @property({type: Boolean})
  mutable?: boolean;

  @property({type: Boolean, attribute: 'disable-hovercards'})
  disableHovercards = false;

  @property({type: Boolean, attribute: 'disable-endpoints'})
  disableEndpoints = false;

  @state()
  runs: CheckRun[] = [];

  static override get styles() {
    return [
      fontStyles,
      submitRequirementsStyles,
      css`
        :host([suppress-title]) .metadata-title {
          display: none;
        }
        .metadata-title {
          color: var(--deemphasized-text-color);
          padding-left: var(--metadata-horizontal-padding);
          margin: 0 0 var(--spacing-s);
          padding-top: var(--spacing-s);
        }
        iron-icon {
          width: var(--line-height-normal, 20px);
          height: var(--line-height-normal, 20px);
          vertical-align: top;
        }
        .requirements,
        section.trigger-votes {
          margin-left: var(--spacing-l);
        }
        .trigger-votes {
          padding-top: var(--spacing-s);
          display: flex;
          flex-wrap: wrap;
          gap: var(--spacing-s);
          /* Setting max-width as defined in Submit Requirements design,
           *  to wrap overflowed items to next row.
           */
          max-width: 390px;
        }
        gr-limited-text.name {
          font-weight: var(--font-weight-bold);
        }
        table {
          border-collapse: collapse;
          border-spacing: 0;
        }
        td {
          padding: var(--spacing-s);
          white-space: nowrap;
        }
        .votes-cell {
          display: flex;
        }
        gr-vote-chip {
          margin-right: var(--spacing-s);
        }
        gr-checks-chip {
          /* .checksChip has top: 2px, this is canceling it */
          margin-top: -2px;
        }
      `,
    ];
  }

  private readonly getChecksModel = resolve(this, checksModelToken);

  override connectedCallback(): void {
    super.connectedCallback();
    subscribe(
      this,
      this.getChecksModel().allRunsLatestPatchsetLatestAttempt$,
      x => (this.runs = x)
    );
  }

  override render() {
    const submit_requirements = orderSubmitRequirements(
      getRequirements(this.change)
    );

    return html` <h3
        class="metadata-title heading-3"
        id="submit-requirements-caption"
      >
        Submit Requirements
      </h3>
      <table class="requirements" aria-labelledby="submit-requirements-caption">
        <thead hidden>
          <tr>
            <th>Status</th>
            <th>Name</th>
            <th>Votes</th>
          </tr>
        </thead>
        <tbody>
          ${submit_requirements.map((requirement, index) =>
            this.renderRequirement(requirement, index)
          )}
        </tbody>
      </table>
      ${this.disableHovercards
        ? ''
        : submit_requirements.map(
            (requirement, index) => html`
              <gr-submit-requirement-hovercard
                for="requirement-${index}-${charsOnly(requirement.name)}"
                .requirement=${requirement}
                .change=${this.change}
                .account=${this.account}
                .mutable=${this.mutable ?? false}
              ></gr-submit-requirement-hovercard>
            `
          )}
      ${this.renderTriggerVotes()}`;
  }

  renderRequirement(requirement: SubmitRequirementResultInfo, index: number) {
    const row = html`
     <td>${this.renderStatus(requirement.status)}</td>
        <td class="name">
          <gr-limited-text
            class="name"
            limit="25"
            .text=${requirement.name}
          ></gr-limited-text>
        </td>
        <td>
          ${this.renderEndpoint(
            requirement,
            html`${this.renderVotesAndChecksChips(requirement)}
            ${this.renderOverrideLabels(requirement)}`
          )}
        </td>
      </tr>
    `;

    if (this.disableHovercards) {
      // when hovercards are disabled, we don't make line focusable (tabindex)
      // since otherwise there is no action associated with the line
      return html`<tr>
        ${row}
      </tr>`;
    } else {
      return html`<tr
        id="requirement-${index}-${charsOnly(requirement.name)}"
        role="button"
        tabindex="0"
      >
        ${row}
      </tr>`;
    }
  }

  renderEndpoint(
    requirement: SubmitRequirementResultInfo,
    slot: TemplateResult
  ) {
    if (this.disableEndpoints)
      return html`<div class="votes-cell">${slot}</div>`;

    const endpointName = this.calculateEndpointName(requirement.name);
    return html`<gr-endpoint-decorator class="votes-cell" name=${endpointName}>
      <gr-endpoint-param
        name="change"
        .value=${this.change}
      ></gr-endpoint-param>
      <gr-endpoint-param
        name="requirement"
        .value=${requirement}
      ></gr-endpoint-param>
      ${slot}
    </gr-endpoint-decorator>`;
  }

  renderStatus(status: SubmitRequirementStatus) {
    const icon = iconForStatus(status);
    return html`<iron-icon
      class=${icon}
      icon="gr-icons:${icon}"
      role="img"
      aria-label=${status.toLowerCase()}
    ></iron-icon>`;
  }

  renderVotesAndChecksChips(requirement: SubmitRequirementResultInfo) {
    if (requirement.status === SubmitRequirementStatus.ERROR) {
      return html`<span class="error">Error</span>`;
    }
    const requirementLabels = extractAssociatedLabels(requirement);
    const allLabels = this.change?.labels ?? {};
    const associatedLabels = Object.keys(allLabels).filter(label =>
      requirementLabels.includes(label)
    );

    const everyAssociatedLabelsIsWithoutVotes = associatedLabels.every(
      label => !hasVotes(allLabels[label])
    );

    const checksChips = this.renderChecks(requirement);

    const requirementWithoutLabelToVoteOn = associatedLabels.length === 0;
    if (requirementWithoutLabelToVoteOn) {
      const status = capitalizeFirstLetter(requirement.status.toLowerCase());
      return checksChips || html`${status}`;
    }

    if (everyAssociatedLabelsIsWithoutVotes) {
      return checksChips || html`No votes`;
    }

    return html`${associatedLabels.map(label =>
      this.renderLabelVote(label, allLabels)
    )}
    ${checksChips}`;
  }

  renderLabelVote(label: string, labels: LabelNameToInfoMap) {
    const labelInfo = labels[label];
    if (isDetailedLabelInfo(labelInfo)) {
      const uniqueApprovals = getAllUniqueApprovals(labelInfo).filter(
        approval => !hasNeutralStatus(labelInfo, approval)
      );
      return uniqueApprovals.map(
        approvalInfo =>
          html`<gr-vote-chip
            .vote=${approvalInfo}
            .label=${labelInfo}
            .more=${(labelInfo.all ?? []).filter(
              other => other.value === approvalInfo.value
            ).length > 1}
          ></gr-vote-chip>`
      );
    } else if (isQuickLabelInfo(labelInfo)) {
      return [html`<gr-vote-chip .label=${labelInfo}></gr-vote-chip>`];
    } else {
      return html``;
    }
  }

  renderChecks(requirement: SubmitRequirementResultInfo) {
    const requirementLabels = extractAssociatedLabels(requirement);
    const requirementRuns = this.runs
      .filter(run => hasResultsOf(run, Category.ERROR))
      .filter(
        run => run.labelName && requirementLabels.includes(run.labelName)
      );
    const runsCount = requirementRuns.reduce(
      (sum, run) => sum + getResultsOf(run, Category.ERROR).length,
      0
    );
    if (runsCount === 0) return;
    const links = [];
    if (requirementRuns.length === 1 && requirementRuns[0].statusLink) {
      links.push(requirementRuns[0].statusLink);
    }
    return html`<gr-checks-chip
      .text=${`${runsCount}`}
      .links=${links}
      .statusOrCategory=${Category.ERROR}
      @click=${() => {
        fireShowPrimaryTab(this, PrimaryTab.CHECKS, false, {
          checksTab: {
            statusOrCategory: Category.ERROR,
          },
        });
      }}
    ></gr-checks-chip>`;
  }

  renderOverrideLabels(requirement: SubmitRequirementResultInfo) {
    if (requirement.status !== SubmitRequirementStatus.OVERRIDDEN) return;
    const requirementLabels = extractAssociatedLabels(
      requirement,
      'onlyOverride'
    ).filter(label => {
      const allLabels = this.change?.labels ?? {};
      return allLabels[label] && hasVotes(allLabels[label]);
    });
    return requirementLabels.map(
      label => html`<span class="overrideLabel">${label}</span>`
    );
  }

  renderTriggerVotes() {
    const labels = this.change?.labels ?? {};
    const triggerVotes = getTriggerVotes(this.change).filter(label =>
      hasVotes(labels[label])
    );
    if (!triggerVotes.length) return;
    return html`<h3 class="metadata-title heading-3">Trigger Votes</h3>
      <section class="trigger-votes">
        ${triggerVotes.map(
          label =>
            html`<gr-trigger-vote
              .label=${label}
              .labelInfo=${labels[label]}
              .change=${this.change}
              .account=${this.account}
              .mutable=${this.mutable ?? false}
              .disableHovercards=${this.disableHovercards}
            ></gr-trigger-vote>`
        )}
      </section>`;
  }

  // not private for tests
  calculateEndpointName(requirementName: string) {
    // remove class name annnotation after ~
    const name = requirementName.split('~')[0];
    const normalizedName = charsOnly(name).toLowerCase();
    return `submit-requirement-${normalizedName}`;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-submit-requirements': GrSubmitRequirements;
  }
}
