/**
 * @license
 * Copyright (C) 2020 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 {CodeOwnersModelMixin} from './code-owners-model-mixin';
import {SuggestionsState, SuggestionsType} from './code-owners-model';
import {getDisplayOwnersGroups, GroupedFiles} from './suggest-owners-util';
import {customElement, property, state} from 'lit/decorators';
import {css, html, LitElement, nothing, PropertyValues} from 'lit';
import {when} from 'lit/directives/when';
import {ifDefined} from 'lit/directives/if-defined';
import {CodeOwnerInfo, CodeOwnersInfo, FetchedFile} from './code-owners-api';
import {
  AccountId,
  AccountInfo,
  GroupInfo,
} from '@gerritcodereview/typescript-api/rest-api';

const SUGGESTION_POLLING_INTERVAL = 1000;

export const OWNER_GROUP_FILE_LIST = 'owner-group-file-list';

@customElement(OWNER_GROUP_FILE_LIST)
export class OwnerGroupFileList extends LitElement {
  @property({type: Array})
  files?: Array<FetchedFile>;

  static override get styles() {
    return [
      css`
        :host {
          display: block;
          max-height: 500px;
          overflow: auto;
        }
        span {
          display: inline-block;
          border-radius: var(--border-radius);
          margin-left: var(--spacing-s);
          padding: 0 var(--spacing-m);
          color: var(--primary-text-color);
          font-size: var(--font-size-small);
        }
        .Renamed {
          background-color: var(--dark-remove-highlight-color);
          margin: var(--spacing-s) 0;
        }
      `,
    ];
  }

  override render() {
    return html`
      <ul>
        ${this.files?.map(file => this.renderFile(file))}
      </ul>
    `;
  }

  private renderFile(file: FetchedFile) {
    return html`
      <li>
        ${this.computeFilePath(file)}
        <strong>${this.computeFileName(file)}</strong>
        ${when(
          !!file.status,
          () => html`
            <span class=${ifDefined(file.status)}> ${file.status} </span>
          `
        )}
      </li>
    `;
  }

  computeFilePath(file: FetchedFile) {
    const parts = file.path.split('/');
    return parts.slice(0, parts.length - 1).join('/') + '/';
  }

  computeFileName(file: FetchedFile) {
    const parts = file.path.split('/');
    return parts.pop();
  }
}

const base = CodeOwnersModelMixin(LitElement);
export const SUGGEST_OWNERS = 'suggest-owners';
@customElement(SUGGEST_OWNERS)
export class SuggestOwners extends base {
  private reportedEvents: Map<
    SuggestionsType,
    {
      fetchingStart: boolean;
      fetchingFinished: boolean;
    }
  >;

  // Bound by the extension point.
  @property({type: Array})
  reviewers?: Array<AccountInfo | GroupInfo>;

  @state()
  suggestedOwners?: Array<GroupedFiles>;

  @state()
  showAllOwners = false;

  private progressUpdateTimer?: number;

  constructor() {
    super();
    this.reportedEvents = new Map();
    for (const suggestionType of Object.values(SuggestionsType)) {
      this.reportedEvents.set(suggestionType, {
        fetchingStart: false,
        fetchingFinished: false,
      });
    }
  }

  static override get styles() {
    return [
      css`
        :host([show-suggestions]) {
          display: block;
          background-color: var(--view-background-color);
          border: 1px solid var(--view-background-color);
          border-radius: var(--border-radius);
          box-shadow: var(--elevation-level-1);
          padding: 0 var(--spacing-m);
          margin: var(--spacing-m) 0;
        }
        .loadingSpin {
          display: inline-block;
        }
        li {
          list-style: none;
        }
        .suggestion-container {
          max-height: 300px;
          overflow-y: auto;
        }
        .flex-break {
          height: 0;
          flex-basis: 100%;
        }
        .suggestion-row,
        .show-all-owners-row {
          display: flex;
          flex-direction: row;
          align-items: flex-start;
        }
        .suggestion-row {
          flex-wrap: wrap;
          border-top: 1px solid var(--border-color);
          padding: var(--spacing-s) 0;
        }
        .show-all-owners-row {
          padding: var(--spacing-m) var(--spacing-xl) var(--spacing-s) 0;
        }
        .show-all-owners-row .loading {
          padding: 0;
        }
        .show-all-owners-row .show-all-label {
          margin-left: auto; /* align label to the right */
        }
        .suggestion-row-indicator {
          margin-right: var(--spacing-s);
          visibility: hidden;
          line-height: 26px;
        }
        .suggestion-row-indicator[visible] {
          visibility: visible;
        }
        .suggestion-row-indicator[visible] gr-icon {
          color: var(--link-color);
          vertical-align: top;
          position: relative;
          font-size: 18px;
          top: 4px; /* (26-18)/2 - 26px line-height and 18px icon */
        }
        .suggestion-group-name {
          width: 260px;
          line-height: 26px;
          text-overflow: ellipsis;
          overflow: hidden;
          padding-right: var(--spacing-s);
          white-space: nowrap;
        }
        .group-name-content {
          display: flex;
          align-items: center;
        }
        .group-name-content .group-name {
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
        .group-name-prefix {
          padding-left: var(--spacing-s);
          white-space: nowrap;
          color: var(--deemphasized-text-color);
        }
        .suggested-owners {
          --account-gap: var(--spacing-xs);
          --negative-account-gap: calc(-1 * var(--account-gap));
          margin: var(--negative-account-gap) 0 0 var(--negative-account-gap);
          flex: 1;
        }
        .fetch-error-content,
        .owned-by-all-users-content,
        .no-owners-content {
          line-height: 26px;
          flex: 1;
          padding-left: var(--spacing-m);
        }

        .owned-by-all-users-content gr-icon {
          font-size: 16px;
          padding-top: 5px;
        }

        .fetch-error-content {
          color: var(--error-text-color);
        }
        .no-owners-content a {
          padding-left: var(--spacing-s);
        }
        .no-owners-content a gr-icon {
          font-size: 16px;
          padding-top: 5px;
        }
        gr-account-label {
          display: inline-block;
          padding: var(--spacing-xs) var(--spacing-m);
          user-select: none;
          border: 1px solid transparent;
          --label-border-radius: 8px;
          /* account-max-length defines the max text width inside account-label.
           With 59 the gr-account-label always has width <= 100px and 5 labels
           are always fit in a single row */
          --account-max-length: 59px;
          border: 1px solid var(--border-color);
          margin: var(--account-gap) 0 0 var(--account-gap);
        }
        gr-account-label:focus {
          outline: none;
        }
        gr-account-label:hover {
          box-shadow: var(--elevation-level-1);
          cursor: pointer;
        }
        gr-account-label[selected] {
          background-color: var(--chip-selected-background-color);
          border: 1px solid var(--chip-selected-background-color);
          color: var(--chip-selected-text-color);
        }
        gr-hovercard {
          max-width: 800px;
        }
        .loading {
          display: flex;
          align-content: center;
          align-items: center;
          justify-content: center;
          padding: var(--spacing-m);
        }
        .loadingSpin {
          width: 18px;
          height: 18px;
          margin-right: var(--spacing-m);
        }
        /* Copied from shared-styles */
        ul {
          border: 0;
          box-sizing: border-box;
          font-size: 100%;
          margin: 0;
          padding: 0;
          vertical-align: baseline;
        }
        *::after,
        *::before {
          box-sizing: border-box;
        }
      `,
    ];
  }

  override disconnectedCallback() {
    super.disconnectedCallback();
    this.stopUpdateProgressTimer();
    this.modelLoader?.pauseActiveSuggestedOwnersLoading();
  }

  protected override willUpdate(changedProperties: PropertyValues): void {
    super.willUpdate(changedProperties);
    if (changedProperties.has('showAllOwners')) {
      this.showAllOwnersChanged();
    }
    if (changedProperties.has('reviewers')) {
      this.onReviewerChanged();
    }
    if (changedProperties.has('showSuggestions')) {
      this.onShowSuggestionsChanged();
    }
    if (
      changedProperties.has('showSuggestions') ||
      changedProperties.has('selectedSuggestionsType')
    ) {
      this.onShowSuggestionsTypeChanged();
    }
    if (changedProperties.has('selectedSuggestionsState')) {
      this.onSuggestionsStateChanged();
    }
    if (
      changedProperties.has('selectedSuggestionsFiles') ||
      changedProperties.has('selectedSuggestionsType') ||
      changedProperties.has('selectedSuggestionsState') ||
      changedProperties.has('reviewers')
    ) {
      this.onSuggestionsFilesChanged();
    }
  }

  override render() {
    if (!this.showSuggestions) return nothing;
    return html`
      <ul class="suggestion-container">
        <li class="show-all-owners-row">
          ${this.renderLoading()} ${this.renderShowAllOwnersCheckbox()}
        </li>
      </ul>
      <ul class="suggestion-container">
        ${when(
          this.suggestedOwners && this.suggestedOwners.length > 0,
          () =>
            (this.suggestedOwners ?? []).map((s, i) =>
              this.renderSuggestion(s, i)
            ),
          () => html`<li class="suggestion-row">No owners found</li>`
        )}
      </ul>
    `;
  }

  private renderLoading() {
    const isLoading =
      this.selectedSuggestionsState === SuggestionsState.Loading;
    if (!isLoading) return nothing;
    return html`
      <p class="loading">
        <span class="loadingSpin"></span>
        ${this.selectedSuggestionsLoadProgress}
      </p>
    `;
  }

  private renderShowAllOwnersCheckbox() {
    return html`
      <label class="show-all-label">
        <input
          id="showAllOwnersCheckbox"
          type="checkbox"
          .checked=${this.showAllOwners}
          @click=${() => {
            this.showAllOwners = !this.showAllOwners;
          }}
        />
        Show all owners
      </label>
    `;
  }

  private renderSuggestion(suggestion: GroupedFiles, suggestionIndex: number) {
    return html`
      <li class="suggestion-row">
        <div
          class="suggestion-row-indicator"
          ?visible=${suggestion.hasSelected}
        >
          <gr-icon filled icon="check_circle"></gr-icon>
        </div>
        ${this.renderSuggestionGroupName(suggestion)}
        ${this.renderSuggestionOwners(suggestion, suggestionIndex)}
      </li>
    `;
  }

  private renderSuggestionGroupName(suggestion: GroupedFiles) {
    return html`
      <div class="suggestion-group-name">
        <div class="group-name-content">
          <span class="group-name"> ${suggestion.groupName.name} </span>
          ${when(
            suggestion.groupName.prefix,
            () => html`
              <span class="group-name-prefix">
                (${suggestion.groupName.prefix})
              </span>
            `
          )}
          ${when(
            !suggestion.expanded,
            () => html`
              <gr-hovercard>
                <owner-group-file-list
                  .files=${suggestion.files}
                ></owner-group-file-list>
              </gr-hovercard>
            `
          )}
        </div>
        ${when(
          suggestion.expanded,
          () => html`
            <owner-group-file-list
              .files=${suggestion.files}
            ></owner-group-file-list>
          `
        )}
      </div>
    `;
  }

  private renderSuggestionOwners(
    suggestion: GroupedFiles,
    suggestionIndex: number
  ) {
    if (suggestion.error) {
      return html` <div class="fetch-error-content">${suggestion.error}</div> `;
    }

    return html`
      ${this.renderSuggestionOwnersNotFound(suggestion)}
      ${this.renderSuggestedOwners(suggestion, suggestionIndex)}
    `;
  }

  private renderSuggestionOwnersNotFound(suggestion: GroupedFiles) {
    if (this.areOwnersFound(suggestion.owners)) return nothing;
    return html`
      <div class="no-owners-content">
        <span>Not found</span>
        <a
          @click=${this.reportDocClick}
          href="https://gerrit.googlesource.com/plugins/code-owners/+/HEAD/resources/Documentation/how-to-use.md#no-code-owners-found"
          target="_blank"
        >
          <gr-icon icon="help" title="read documentation"></gr-icon>
        </a>
      </div>
    `;
  }

  private renderSuggestedOwners(
    suggestion: GroupedFiles,
    suggestionIndex: number
  ) {
    if (suggestion.owners?.owned_by_all_users) {
      return html`
        <div class="owned-by-all-users-content">
          <gr-icon icon="info" filled></gr-icon>
          <span>${this.getOwnedByAllUsersContent()}</span>
        </div>
      `;
    }

    return html`
      ${when(this.showAllOwners, () => html`<div class="flex-break"></div>`)}
      <ul class="suggested-owners">
        ${(suggestion.owners?.code_owners ?? []).map((owner, ownerIndex) =>
          this.renderSuggestedOwner(owner, suggestionIndex, ownerIndex)
        )}
      </ul>
    `;
  }

  private renderSuggestedOwner(
    owner: CodeOwnerInfo,
    suggestionIndex: number,
    ownerIndex: number
  ) {
    return html`<gr-account-label
      .account=${owner.account}
      ?selected=${!!owner.selected}
      @click=${() => this.toggleAccount(suggestionIndex, ownerIndex)}
    ></gr-account-label>`;
  }

  private onShowSuggestionsChanged() {
    if (!this.showSuggestions) {
      return;
    }
    // this is more of a hack to let review input lose focus
    // to avoid suggestion dropdown
    // gr-autocomplete has a internal state for tracking focus
    // that will be canceled if any click happens outside of
    // it's target
    window.setTimeout(() => this.click(), 100);
  }

  private onShowSuggestionsTypeChanged() {
    if (!this.showSuggestions) {
      this.modelLoader?.pauseActiveSuggestedOwnersLoading();
      return;
    }
    const selectedSuggestionsType = this.selectedSuggestionsType;
    if (selectedSuggestionsType === undefined) {
      return;
    }
    this.modelLoader?.loadSuggestions(selectedSuggestionsType);
    // The progress is updated at the next _progressUpdateTimer tick.
    // Without explicit call to updateLoadSuggestionsProgress it looks like
    // a slow reaction to checkbox.
    this.modelLoader?.updateLoadSelectedSuggestionsProgress();

    if (!this.reportedEvents.get(selectedSuggestionsType)?.fetchingStart) {
      this.reportedEvents.get(selectedSuggestionsType)!.fetchingStart = true;
      this.reporting?.reportLifeCycle('owners-suggestions-fetching-start', {
        type: selectedSuggestionsType,
      });
    }
  }

  _startUpdateProgressTimer() {
    if (this.progressUpdateTimer) return;
    this.progressUpdateTimer = window.setInterval(() => {
      this.modelLoader?.updateLoadSelectedSuggestionsProgress();
    }, SUGGESTION_POLLING_INTERVAL);
  }

  private stopUpdateProgressTimer() {
    if (!this.progressUpdateTimer) return;
    window.clearInterval(this.progressUpdateTimer);
    this.progressUpdateTimer = undefined;
  }

  private onSuggestionsStateChanged() {
    this.stopUpdateProgressTimer();
    if (this.selectedSuggestionsState === SuggestionsState.Loading) {
      this._startUpdateProgressTimer();
    }
  }

  override loadPropertiesAfterModelChanged() {
    super.loadPropertiesAfterModelChanged();
    this.stopUpdateProgressTimer();
    this.modelLoader?.loadAreAllFilesApproved();
  }

  private getReviewersIdSet(): Set<AccountId> {
    return new Set(
      (this.reviewers ?? [])
        // Ugly hack, but we only care about accounts.
        .map(account => (account as unknown as AccountInfo)._account_id)
        .filter(account_id => account_id !== undefined)
    ) as Set<AccountId>;
  }

  private onSuggestionsFilesChanged() {
    if (
      this.selectedSuggestionsFiles === undefined ||
      this.reviewers === undefined ||
      this.selectedSuggestionsType === undefined ||
      this.selectedSuggestionsState === undefined
    )
      return;

    const allOwners =
      this.model?.getSuggestionsByType(SuggestionsType.ALL_SUGGESTIONS)
        ?.files ?? [];

    const allOwnersByPathMap = this.getOwnersByPathMap(allOwners);
    const reviewersIdSet = this.getReviewersIdSet();
    const selectedSuggestionsType = this.selectedSuggestionsType;
    const suggestionsState = this.selectedSuggestionsState;

    const groups = getDisplayOwnersGroups(
      this.selectedSuggestionsFiles,
      allOwnersByPathMap,
      reviewersIdSet,
      selectedSuggestionsType !== SuggestionsType.ALL_SUGGESTIONS
    );
    // The updateLoadSuggestionsProgress method also updates suggestions
    this.updateSuggestions(groups);
    this.updateAllChips(this.reviewers);

    if (suggestionsState !== SuggestionsState.Loaded) return;
    if (!this.reportedEvents.get(selectedSuggestionsType)!.fetchingFinished) {
      this.reportedEvents.get(selectedSuggestionsType)!.fetchingFinished = true;
      const reportDetails = groups.reduce(
        (details, cur) => {
          details.totalGroups++;
          details.stats.push([
            cur.files.length,
            cur.owners && cur.owners.code_owners
              ? cur.owners.code_owners.length
              : 0,
          ]);
          return details;
        },
        {
          totalGroups: 0,
          stats: [] as Array<Array<number>>,
          type: selectedSuggestionsType,
        }
      );
      this.reporting?.reportLifeCycle(
        'owners-suggestions-fetching-finished',
        reportDetails
      );
    }
  }

  private getOwnersByPathMap(files?: Array<FetchedFile>) {
    return new Map(
      (files || [])
        .filter(file => !file.info.error && file.info.owners)
        .map(file => [file.path, file.info.owners])
    );
  }

  private updateSuggestions(suggestions: Array<GroupedFiles>) {
    // update group names and files, no modification on owners or error
    const suggestedOwners = suggestions.map(suggestion =>
      this.formatSuggestionInfo(suggestion)
    );
    // move owned_by_all_users to the bottom:
    const index = suggestedOwners.findIndex(
      suggestion => suggestion.owners?.owned_by_all_users
    );
    if (index >= 0) {
      suggestedOwners.push(suggestedOwners.splice(index, 1)[0]);
    }
    this.suggestedOwners = suggestedOwners;
  }

  onReviewerChanged() {
    this.updateAllChips(this.reviewers);
  }

  formatSuggestionInfo(suggestion: GroupedFiles): GroupedFiles {
    const res = {
      groupName: suggestion.groupName,
      files: suggestion.files.slice(),
      owners: undefined as CodeOwnersInfo | undefined,
      error: undefined as Error | undefined,
    } as GroupedFiles;
    if (suggestion.owners) {
      const codeOwners = (suggestion.owners.code_owners || []).map(owner => {
        const updatedOwner = {...owner};
        const reviewers = this.change?.reviewers.REVIEWER;
        if (
          reviewers &&
          reviewers.find(
            reviewer => reviewer._account_id === owner.account?._account_id
          )
        ) {
          updatedOwner.selected = true;
        }
        return updatedOwner;
      });
      res.owners = {
        owned_by_all_users: !!suggestion.owners.owned_by_all_users,
        code_owners: codeOwners,
      };
    } else {
      res.owners = {
        owned_by_all_users: false,
        code_owners: [],
      };
    }

    res.error = suggestion.error;
    return res;
  }

  addAccount(owner: CodeOwnerInfo) {
    owner.selected = true;
    this.dispatchEvent(
      new CustomEvent('add-reviewer', {
        detail: {
          reviewer: {...owner.account, _pendingAdd: true},
        },
        composed: true,
        bubbles: true,
      })
    );
    this.reporting?.reportInteraction('add-reviewer');
  }

  removeAccount(owner: CodeOwnerInfo) {
    owner.selected = false;
    this.dispatchEvent(
      new CustomEvent('remove-reviewer', {
        detail: {
          reviewer: {...owner.account, _pendingAdd: true},
        },
        composed: true,
        bubbles: true,
      })
    );
    this.reporting?.reportInteraction('remove-reviewer');
  }

  toggleAccount(suggestionIndex: number, ownerIndex: number) {
    const owner =
      this.suggestedOwners![suggestionIndex]?.owners?.code_owners[ownerIndex];
    if (!owner) return;
    if (owner.selected) {
      this.removeAccount(owner);
    } else {
      this.addAccount(owner);
    }
  }

  private updateAllChips(accounts: Array<AccountInfo> | undefined) {
    if (!this.suggestedOwners || !accounts) return;
    // update all occurences
    this.suggestedOwners.forEach((suggestion, sId) => {
      let hasSelected = false;
      suggestion.owners?.code_owners.forEach((owner, oId) => {
        if (
          accounts.some(
            account => account._account_id === owner!.account!._account_id
          )
        ) {
          this.suggestedOwners![sId].owners!.code_owners[oId].selected = true;
          hasSelected = true;
        } else {
          this.suggestedOwners![sId].owners!.code_owners[oId].selected = false;
        }
      });
      const nonServiceUser = (account: AccountInfo) =>
        !account.tags || account.tags.indexOf('SERVICE_USER') < 0;
      if (
        suggestion.owners?.owned_by_all_users &&
        accounts.some(nonServiceUser)
      ) {
        hasSelected = true;
      }
      this.suggestedOwners![sId].hasSelected = hasSelected;
    });
  }

  private reportDocClick() {
    this.reporting?.reportInteraction('code-owners-doc-click', {
      section: 'no owners found',
    });
  }

  private areOwnersFound(owners: CodeOwnersInfo | undefined) {
    return (
      owners && (owners.code_owners.length > 0 || !!owners.owned_by_all_users)
    );
  }

  private getOwnedByAllUsersContent() {
    if (this.selectedSuggestionsState === SuggestionsState.Loading) {
      return 'Any user can approve';
    }
    // If all users own all the files in the change suggestedOwners.length === 1
    // (suggestedOwners - collection of owners groupbed by owners)
    return this.suggestedOwners && this.suggestedOwners.length === 1
      ? 'Any user can approve. Please select a user manually'
      : 'Any user from the other files can approve';
  }

  private showAllOwnersChanged() {
    // The first call to this method happens before model is set.
    if (!this.model) return;
    this.model.setSelectedSuggestionType(
      this.showAllOwners
        ? SuggestionsType.ALL_SUGGESTIONS
        : SuggestionsType.BEST_SUGGESTIONS
    );
  }
}
