/**
 * @license
 * Copyright (C) 2024 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 {
  css,
  html,
  LitElement,
  PropertyValues,
  nothing,
  CSSResult,
  unsafeCSS,
} from 'lit';
import {ifDefined} from 'lit/directives/if-defined.js';
import {OwnersMixin} from './owners-mixin';
import {customElement, property} from 'lit/decorators.js';
import {
  AccountInfo,
  ChangeInfo,
  ChangeStatus,
  EmailAddress,
  RevisionInfo,
  EDIT,
} from '@gerritcodereview/typescript-api/rest-api';
import {User, UserRole} from './owners-model';
import {
  FilesOwners,
  hasOwnersSubmitRequirement,
  isOwner,
  OwnedFiles,
} from './owners-service';
import {
  computeDisplayPath,
  diffFilePaths,
  encodeURL,
  getBaseUrl,
  truncatePath,
} from './utils';

export enum FileStatus {
  NEEDS_APPROVAL = 'missing',
  APPROVED = 'approved',
  AUTO_APPROVED = 'autoApproved',
}

const STATUS_ICON = {
  [FileStatus.NEEDS_APPROVAL]: 'schedule',
  [FileStatus.APPROVED]: 'check',
  [FileStatus.AUTO_APPROVED]: 'published_with_changes',
};

interface OwnedFileInfo {
  status: FileStatus;
  file: string;
}

export interface OwnedFilesInfo {
  ownedFiles: OwnedFileInfo[];
  numberOfPending: number;
  numberOfApproved: number;
}

const common = OwnersMixin(LitElement);

class OwnedFilesCommon extends common {
  @property({type: Object})
  revision?: RevisionInfo;

  protected ownedFilesInfo?: OwnedFilesInfo;

  protected override willUpdate(changedProperties: PropertyValues): void {
    super.willUpdate(changedProperties);
    this.computeOwnedFiles();

    this.hidden = shouldHide(
      this.change,
      this.revision,
      this.user,
      this.ownedFilesInfo?.ownedFiles
    );
  }

  static commonStyles(): CSSResult[] {
    const template = document.querySelector(
      'dom-module#shared-styles > template'
    ) as HTMLTemplateElement;
    const sharedStyles = css`
      ${unsafeCSS(template?.content?.querySelector('style')?.textContent)}
    `;
    return [sharedStyles, window?.Gerrit?.styles.font as CSSResult];
  }

  private computeOwnedFiles() {
    this.ownedFilesInfo = ownedFiles(this.user?.account, this.filesOwners);
  }
}

export const OWNED_FILES_TAB_HEADER = 'owned-files-tab-header';
@customElement(OWNED_FILES_TAB_HEADER)
export class OwnedFilesTabHeader extends OwnedFilesCommon {
  @property({type: String, reflect: true, attribute: 'files-status'})
  filesStatus?: FileStatus;

  private ownedFiles: number | undefined;

  static override get styles() {
    return [
      ...OwnedFilesCommon.commonStyles(),
      css`
        [hidden] {
          display: none;
        }
        gr-icon {
          padding: var(--spacing-xs) 0px;
          margin-left: 3px;
        }
        :host([files-status='approved']) gr-icon.status,
        :host([files-status='autoApproved']) gr-icon.status {
          color: var(--positive-green-text-color);
        }
        :host([files-status='missing']) gr-icon.status {
          color: #ffa62f;
        }
      `,
    ];
  }

  protected override willUpdate(changedProperties: PropertyValues): void {
    super.willUpdate(changedProperties);

    if (this.hidden || this.ownedFilesInfo === undefined) {
      this.filesStatus = undefined;
      this.ownedFiles = undefined;
    } else {
      [this.filesStatus, this.ownedFiles] =
        this.ownedFilesInfo.numberOfPending > 0
          ? [FileStatus.NEEDS_APPROVAL, this.ownedFilesInfo.numberOfPending]
          : [FileStatus.APPROVED, this.ownedFilesInfo.numberOfApproved];
    }
  }

  override render() {
    // even if `nothing` is returned Gerrit still shows the pointer and allows
    // clicking at it, redirecting to the empty tab when done; traverse through
    // the shadowRoots down to the tab and disable/enable it when needed
    const tabParent = document
      .querySelector('#pg-app')
      ?.shadowRoot?.querySelector('#app-element')
      ?.shadowRoot?.querySelector('main > gr-change-view')
      ?.shadowRoot?.querySelector(
        '#tabs > paper-tab[data-name="change-view-tab-header-owners"]'
      );
    if (this.hidden) {
      if (tabParent && !tabParent.getAttribute('disabled')) {
        tabParent.setAttribute('disabled', 'disabled');
      }
      return nothing;
    }
    if (tabParent && tabParent.getAttribute('disabled')) {
      tabParent.removeAttribute('disabled');
    }

    if (
      this.ownedFilesInfo === undefined ||
      this.filesStatus === undefined ||
      this.ownedFiles === undefined
    ) {
      return html`<div>Owned Files</div>`;
    }

    const icon = STATUS_ICON[this.filesStatus];
    const [info, summary] = this.buildInfoAndSummary(
      this.filesStatus,
      this.ownedFilesInfo.numberOfApproved,
      this.ownedFilesInfo.numberOfPending
    );
    return html` <div>
      Owned Files
      <gr-tooltip-content
        title=${info}
        aria-label=${summary}
        aria-description=${info}
        has-tooltip
      >
        <gr-icon
          id="owned-files-status"
          class="status"
          icon=${icon}
          aria-hidden="true"
        ></gr-icon>
      </gr-tooltip-content>
    </div>`;
  }

  private buildInfoAndSummary(
    filesStatus: FileStatus,
    filesApproved: number,
    filesPending: number
  ): [string, string] {
    const allFilesApproved =
      filesStatus === FileStatus.APPROVED ||
      filesStatus === FileStatus.AUTO_APPROVED;
    const pendingInfo =
      filesPending > 0
        ? `Missing approval for ${filesPending} file${
            filesPending > 1 ? 's' : ''
          }`
        : '';
    const approvedInfo =
      filesApproved > 0
        ? `${filesApproved} file${
            filesApproved > 1 ? 's' : ''
          } already approved.`
        : '';
    const info = `${
      allFilesApproved
        ? approvedInfo
        : `${pendingInfo}${filesApproved > 0 ? ` and ${approvedInfo}` : '.'}`
    }`;
    const summary = `${allFilesApproved ? 'Approved' : 'Missing'}`;
    return [info, summary];
  }
}

@customElement('gr-owned-files-list')
export class GrOwnedFilesList extends LitElement {
  @property({type: Object})
  change?: ChangeInfo;

  @property({type: Object})
  revision?: RevisionInfo;

  @property({type: Array})
  ownedFiles?: OwnedFileInfo[];

  static override get styles() {
    return [
      ...OwnedFilesCommon.commonStyles(),
      css`
        :host {
          display: block;
        }
        .row {
          align-items: center;
          border-top: 1px solid var(--border-color);
          display: flex;
          min-height: calc(var(--line-height-normal) + 2 * var(--spacing-s));
          padding: var(--spacing-xs) var(--spacing-l);
        }
        .header-row {
          padding-left: var(--spacing-m);
          background-color: var(--background-color-secondary);
        }
        .file-row {
          padding-left: var(--spacing-m);
          cursor: pointer;
        }
        .file-row:hover {
          background-color: var(--hover-background-color);
        }
        .file-row.selected {
          background-color: var(--selection-background-color);
        }
        .status {
          padding: inherit;
        }
        .path {
          padding: inherit;
          cursor: pointer;
          flex: 1;
          /* Wrap it into multiple lines if too long. */
          white-space: normal;
          word-break: break-word;
        }
        gr-icon.status.approved {
          color: var(--positive-green-text-color);
        }
        gr-icon.status.autoApproved {
          color: var(--positive-green-text-color);
        }
        gr-icon.status.missing {
          color: #ffa62f;
        }
        .matchingFilePath {
          color: var(--deemphasized-text-color);
        }
        .newFilePath {
          color: var(--primary-text-color);
        }
        .fileName {
          color: var(--link-color);
        }
        .truncatedFileName {
          display: none;
        }
        .row:focus {
          outline: none;
        }
        .row:hover {
          opacity: 100;
        }
        .pathLink {
          display: inline-block;
          margin: -2px 0;
          padding: var(--spacing-s) 0;
          text-decoration: none;
        }
        .pathLink:hover span.fullFileName,
        .pathLink:hover span.truncatedFileName {
          text-decoration: underline;
        }
      `,
    ];
  }

  override render() {
    if (!this.change || !this.revision || !this.ownedFiles) return nothing;

    return html`
      <div id="container" role="grid" aria-label="Owned files list">
        ${this.renderOwnedFilesHeaderRow()}
        ${this.ownedFiles?.map((ownedFile, index) =>
          this.renderOwnedFileRow(ownedFile, index)
        )}
      </div>
    `;
  }

  private renderOwnedFilesHeaderRow() {
    return html`
      <div class="header-row row" role="row">
        <div class="status" role="columnheader">Status</div>
        <div class="path" role="columnheader">File</div>
      </div>
    `;
  }

  private renderOwnedFileRow(ownedFile: OwnedFileInfo, index: number) {
    return html`
      <div
        class="file-row row"
        tabindex="-1"
        role="row"
        aria-label=${ownedFile.file}
      >
        ${this.renderFileStatus(ownedFile.status)}
        ${this.renderFilePath(ownedFile.file, index)}
      </div>
    `;
  }

  private renderFileStatus(status: FileStatus) {
    const icon = STATUS_ICON[status];
    return html`
      <span class="status" role="gridcell">
        <gr-icon
          class="status ${status}"
          icon=${icon}
          aria-hidden="true"
        ></gr-icon>
      </span>
    `;
  }

  private renderFilePath(file: string, index: number) {
    const displayPath = computeDisplayPath(file);
    const previousFile = (this.ownedFiles ?? [])[index - 1];
    return html`
      <span class="path" role="gridcell">
        <a
          class="pathLink"
          href=${ifDefined(computeDiffUrl(file, this.change, this.revision))}
        >
          <span title=${displayPath} class="fullFileName">
            ${this.renderStyledPath(file, previousFile?.file)}
          </span>
          <span title=${displayPath} class="truncatedFileName">
            ${truncatePath(displayPath)}
          </span>
        </a>
      </span>
    `;
  }

  private renderStyledPath(filePath: string, previousFilePath?: string) {
    const {matchingFolders, newFolders, fileName} = diffFilePaths(
      filePath,
      previousFilePath
    );
    return [
      matchingFolders.length > 0
        ? html`<span class="matchingFilePath">${matchingFolders}</span>`
        : nothing,
      newFolders.length > 0
        ? html`<span class="newFilePath">${newFolders}</span>`
        : nothing,
      html`<span class="fileName">${fileName}</span>`,
    ];
  }
}

export const OWNED_FILES_TAB_CONTENT = 'owned-files-tab-content';
@customElement(OWNED_FILES_TAB_CONTENT)
export class OwnedFilesTabContent extends OwnedFilesCommon {
  static override get styles() {
    return [
      ...OwnedFilesCommon.commonStyles(),
      css`
        :host {
          display: block;
        }
      `,
    ];
  }

  override render() {
    if (this.hidden) return nothing;

    return html`
      <gr-owned-files-list
        id="ownedFilesList"
        .change=${this.change}
        .revision=${this.revision}
        .ownedFiles=${this.ownedFilesInfo?.ownedFiles}
      >
      </gr-owned-files-list>
    `;
  }
}

export function shouldHide(
  change?: ChangeInfo,
  revision?: RevisionInfo,
  user?: User,
  ownedFiles?: OwnedFileInfo[]
) {
  // don't show owned files when no change or change is abandoned/merged or being edited or viewing not current PS
  if (
    change === undefined ||
    change.status === ChangeStatus.ABANDONED ||
    change.status === ChangeStatus.MERGED ||
    revision === undefined ||
    revision._number === EDIT ||
    change.current_revision !== revision.commit?.commit
  ) {
    return true;
  }

  // show owned files if user owns anything
  if (hasOwnersSubmitRequirement(change)) {
    return (
      !user ||
      user.role === UserRole.ANONYMOUS ||
      (ownedFiles ?? []).length === 0
    );
  }
  return true;
}

function collectOwnedFiles(
  owner: AccountInfo,
  groupPrefix: string,
  files: OwnedFiles,
  fileStatus: FileStatus,
  emailWithoutDomain?: string
): OwnedFileInfo[] {
  const ownedFiles = [];
  for (const file of Object.keys(files ?? [])) {
    if (
      files[file].find(fileOwner => {
        if (isOwner(fileOwner)) {
          return fileOwner.id === owner._account_id;
        }

        return (
          !fileOwner.name?.startsWith(groupPrefix) &&
          (fileOwner.name === emailWithoutDomain ||
            fileOwner.name === owner.name)
        );
      })
    ) {
      ownedFiles.push({file, status: fileStatus} as OwnedFileInfo);
    }
  }

  return ownedFiles;
}

export function ownedFiles(
  owner?: AccountInfo,
  filesOwners?: FilesOwners
): OwnedFilesInfo | undefined {
  if (
    !owner ||
    !filesOwners ||
    (!filesOwners.files &&
      !filesOwners.files_approved &&
      !filesOwners.files_auto_approved)
  ) {
    return;
  }

  const groupPrefix = 'group/';
  const emailWithoutDomain = toEmailWithoutDomain(owner.email);
  const pendingFiles = collectOwnedFiles(
    owner,
    groupPrefix,
    filesOwners.files,
    FileStatus.NEEDS_APPROVAL,
    emailWithoutDomain
  );
  const approvedFiles = collectOwnedFiles(
    owner,
    groupPrefix,
    filesOwners.files_approved,
    FileStatus.APPROVED,
    emailWithoutDomain
  );
  const autoApprovedFiles = collectOwnedFiles(
    owner,
    groupPrefix,
    filesOwners.files_auto_approved ?? {},
    FileStatus.AUTO_APPROVED,
    emailWithoutDomain
  );
  return {
    ownedFiles: [...pendingFiles, ...approvedFiles, ...autoApprovedFiles],
    numberOfPending: pendingFiles.length,
    numberOfApproved: approvedFiles.length + autoApprovedFiles.length,
  } as OwnedFilesInfo;
}

export function computeDiffUrl(
  file: string,
  change?: ChangeInfo,
  revision?: RevisionInfo
) {
  if (change === undefined || revision?._number === undefined) {
    return;
  }

  let repo = '';
  if (change.project) repo = `${encodeURL(change.project)}/+/`;

  // TODO it can be a range of patchsets but `PatchRange` is not passed to the `change-view-tab-content` :/ fix in Gerrit?
  const range = `/${revision._number}`;

  const path = `/${encodeURL(file)}`;

  return `${getBaseUrl()}/c/${repo}${change._number}${range}${path}`;
}

function toEmailWithoutDomain(email?: EmailAddress): string | undefined {
  const startDomainIndex = email?.indexOf('@');
  return startDomainIndex ? email?.substring(0, startDomainIndex) : undefined;
}
