/**
 * @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 {
  SuggestionsType,
  BestSuggestionsLimit,
  AllSuggestionsLimit,
  UserRole,
  Status,
  FileStatus,
} from './code-owners-model';
import {OwnersProvider, FetchStatus} from './code-owners-fetcher';
import {
  CodeOwnersApi,
  CodeOwnersCacheApi,
  FetchedFile,
  FetchedOwner,
  FileCodeOwnerStatusInfo,
  OwnerStatus,
} from './code-owners-api';
import {RestPluginApi} from '@gerritcodereview/typescript-api/rest';
import {
  AccountDetailInfo,
  AccountInfo,
  ChangeInfo,
} from '@gerritcodereview/typescript-api/rest-api';

/**
 * Specifies status for a change. The same as ChangeStatus enum in gerrit
 *
 * @enum
 */
const ChangeStatus = {
  ABANDONED: 'ABANDONED',
  MERGED: 'MERGED',
  NEW: 'NEW',
};

let ownerService: CodeOwnerService | undefined;

interface CodeOwnerServiceOptions {
  maxConcurrentRequests?: number;
}

/**
 * Service for the data layer used in the plugin UI.
 */
export class CodeOwnerService {
  private codeOwnersCacheApi: CodeOwnersCacheApi;

  private ownersProviders: Map<SuggestionsType, OwnersProvider>;

  constructor(
    readonly restApi: RestPluginApi,
    readonly change: ChangeInfo,
    options: CodeOwnerServiceOptions = {}
  ) {
    const codeOwnersApi = new CodeOwnersApi(restApi);
    this.codeOwnersCacheApi = new CodeOwnersCacheApi(codeOwnersApi, change);

    const providerOptions = {
      maxConcurrentRequests: options.maxConcurrentRequests || 10,
    };
    this.ownersProviders = new Map();
    this.ownersProviders.set(
      SuggestionsType.BEST_SUGGESTIONS,
      new OwnersProvider(restApi, change, {
        ...providerOptions,
        ownersLimit: BestSuggestionsLimit,
      })
    );
    this.ownersProviders.set(
      SuggestionsType.ALL_SUGGESTIONS,
      new OwnersProvider(restApi, change, {
        ...providerOptions,
        ownersLimit: AllSuggestionsLimit,
      })
    );
  }

  /**
   * Fetch the account.
   */
  getAccount(): Promise<AccountDetailInfo | undefined> {
    return this.codeOwnersCacheApi.getAccount();
  }

  /**
   * Prefetch data
   */
  async prefetch() {
    try {
      await Promise.all([this.getAccount(), this.getStatus()]);
    } catch {
      // Ignore any errors during prefetch.
      // The same call from a different place throws the same exception
      // again. The CodeOwnerService is not responsible for error processing.
    }
  }

  /**
   * Returns the role of the current user. The returned value reflects the
   * role of the user at the time when the change is loaded.
   * For example, if a user removes themselves as a reviewer, the returned
   * role 'REVIEWER' remains unchanged until the change view is reloaded.
   */
  async getLoggedInUserInitialRole(): Promise<UserRole> {
    const account = await this.getAccount();
    if (!account) {
      return UserRole.ANONYMOUS;
    }
    const change = this.change;
    if (
      change.revisions &&
      change.current_revision &&
      change.revisions[change.current_revision]
    ) {
      const commit = change.revisions[change.current_revision].commit;
      if (
        commit &&
        commit.author &&
        account.email &&
        commit.author.email === account.email
      ) {
        return UserRole.AUTHOR;
      }
    }
    if (change.owner._account_id === account._account_id) {
      return UserRole.CHANGE_OWNER;
    }
    if (change.reviewers) {
      if (this.accountInReviewers(change.reviewers.REVIEWER, account)) {
        return UserRole.REVIEWER;
      } else if (this.accountInReviewers(change.reviewers.CC, account)) {
        return UserRole.CC;
      } else if (this.accountInReviewers(change.reviewers.REMOVED, account)) {
        return UserRole.REMOVED_REVIEWER;
      }
    }
    return UserRole.OTHER;
  }

  private accountInReviewers(
    reviewers: AccountInfo[] | undefined,
    account: AccountDetailInfo
  ) {
    if (!reviewers) {
      return false;
    }
    return reviewers.some(
      reviewer => reviewer._account_id === account._account_id
    );
  }

  async getStatus(): Promise<Status> {
    const status = await this.getStatusImpl();
    if (status.enabled && this.isOnOlderPatchset(status.patchsetNumber)) {
      // status is returned for an older patchset. Abort, re-init and refetch
      // new status - it is expected, that after several retry a status
      // for the newest patchset is returned
      this.reset();
      void this.prefetch()
      return await this.getStatus();
    }
    return status;
  }

  private async getStatusImpl() {
    const enabled = await this.isCodeOwnerEnabled();
    if (!enabled) {
      return {
        patchsetNumber: 0,
        enabled: false,
        codeOwnerStatusMap: new Map<string, FileStatus>(),
        rawStatuses: [],
        newerPatchsetUploaded: false,
      };
    }

    const ownerStatus = await this.codeOwnersCacheApi.listOwnerStatus();

    return {
      enabled: true,
      patchsetNumber: ownerStatus.patch_set_number,
      codeOwnerStatusMap: this.formatStatuses(
        ownerStatus.file_code_owner_statuses
      ),
      rawStatuses: ownerStatus.file_code_owner_statuses,
      newerPatchsetUploaded: this.isOnNewerPatchset(
        ownerStatus.patch_set_number
      ),
      accounts: ownerStatus.accounts,
    };
  }

  async areAllFilesApproved() {
    const {rawStatuses} = await this.getStatus();
    return !rawStatuses.some(status => {
      const oldPathStatus = status.old_path_status;
      const newPathStatus = status.new_path_status;
      // For deleted files, no new_path_status exists
      return (
        (newPathStatus && newPathStatus.status !== OwnerStatus.APPROVED) ||
        (oldPathStatus && oldPathStatus.status !== OwnerStatus.APPROVED)
      );
    });
  }

  private ownersProvider(suggestionsType: SuggestionsType) {
    return this.ownersProviders.get(suggestionsType)!;
  }

  /**
   * Gets which files are owned by the given user.
   */
  async getOwnedPaths() {
    const enabled = await this.isCodeOwnerEnabled();
    if (!enabled) {
      return Promise.resolve(undefined);
    }
    return this.codeOwnersCacheApi.listOwnedPaths();
  }

  /**
   * Gets owner suggestions.
   */
  async getSuggestedOwners(suggestionsType: SuggestionsType) {
    const {codeOwnerStatusMap} = await this.getStatus();
    const ownersProvider = this.ownersProvider(suggestionsType);

    await ownersProvider!.fetchSuggestedOwners(codeOwnerStatusMap);

    return {
      finished: ownersProvider.getStatus() === FetchStatus.FINISHED,
      status: ownersProvider.getStatus(),
      progress: ownersProvider.getProgressString(),
      files: this.getFilesWithStatuses(
        codeOwnerStatusMap,
        ownersProvider.getFiles()
      ),
    };
  }

  async getSuggestedOwnersProgress(suggestionsType: SuggestionsType) {
    const {codeOwnerStatusMap} = await this.getStatus();
    const ownersProvider = this.ownersProvider(suggestionsType);
    return {
      finished: ownersProvider.getStatus() === FetchStatus.FINISHED,
      status: ownersProvider.getStatus(),
      progress: ownersProvider.getProgressString(),
      files: this.getFilesWithStatuses(
        codeOwnerStatusMap,
        ownersProvider.getFiles()
      ),
    };
  }

  pauseSuggestedOwnersLoading(suggestionsType: SuggestionsType) {
    this.ownersProvider(suggestionsType).pause();
  }

  resumeSuggestedOwnersLoading(suggestionsType: SuggestionsType) {
    this.ownersProvider(suggestionsType).resume();
  }

  private formatStatuses(statuses?: Array<FileCodeOwnerStatusInfo>) {
    // convert the array of statuses to map between file path -> status
    return (statuses ?? []).reduce((prev, cur) => {
      const newPathStatus = cur.new_path_status;
      const oldPathStatus = cur.old_path_status;
      if (oldPathStatus) {
        prev.set(oldPathStatus.path, {
          changeType: cur.change_type,
          status: oldPathStatus.status,
          newPath: newPathStatus ? newPathStatus.path : null,
          reasons: oldPathStatus.reasons,
        });
      }
      if (newPathStatus) {
        prev.set(newPathStatus.path, {
          changeType: cur.change_type,
          status: newPathStatus.status,
          oldPath: oldPathStatus ? oldPathStatus.path : null,
          reasons: newPathStatus.reasons,
        });
      }
      return prev;
    }, new Map<string, FileStatus>());
  }

  private computeFileStatus(
    fileStatusMap: Map<string, FileStatus>,
    path: string
  ) {
    // empty for modified files and old-name files
    // Show `Renamed` for renamed file
    const status = fileStatusMap.get(path);
    if (status && status.oldPath) {
      return 'Renamed';
    }
    return;
  }

  private getFilesWithStatuses(
    codeOwnerStatusMap: Map<string, FileStatus>,
    files: Array<{
      path: string;
      info: FetchedOwner;
    }>
  ): Array<FetchedFile> {
    return files
      .map(file => {
        return {
          path: file.path,
          info: file.info,
          status: this.computeFileStatus(codeOwnerStatusMap, file.path),
        };
      })
      .sort((a, b) => CodeOwnerService.specialFilePathCompare(a.path, b.path));
  }

  private isOnNewerPatchset(patchsetId: number) {
    if (this.change.current_revision === undefined) return false;
    const latestRevision = this.change.revisions![this.change.current_revision];
    if (latestRevision._number === 'edit') {
      return false;
    }
    return patchsetId > latestRevision._number;
  }

  private isOnOlderPatchset(patchsetId: number) {
    if (this.change.current_revision === undefined) return false;
    const latestRevision = this.change.revisions![this.change.current_revision];
    if (latestRevision._number === 'edit') {
      return false;
    }
    return patchsetId < latestRevision._number;
  }

  reset() {
    for (const provider of Object.values(this.ownersProviders)) {
      provider.reset();
    }
    const codeOwnersApi = new CodeOwnersApi(this.restApi);
    this.codeOwnersCacheApi = new CodeOwnersCacheApi(
      codeOwnersApi,
      this.change
    );
  }

  async getBranchConfig() {
    return this.codeOwnersCacheApi.getBranchConfig();
  }

  async isCodeOwnerEnabled() {
    if (
      this.change.status === ChangeStatus.ABANDONED ||
      this.change.status === ChangeStatus.MERGED
    ) {
      return false;
    }
    const config = await this.getBranchConfig();
    return config && !config.disabled;
  }

  static getOwnerService(restApi: RestPluginApi, change: ChangeInfo) {
    if (!ownerService || ownerService.change !== change) {
      ownerService = new CodeOwnerService(restApi, change, {
        // Chrome has a limit of 6 connections per host name, and a max of 10 connections.
        maxConcurrentRequests: 6,
      });
      ownerService.prefetch();
    }
    return ownerService;
  }

  // Only used for tests
  static reset() {
    if (!ownerService) return;
    ownerService.reset();
    ownerService = undefined;
  }

  // Copied from https://cs.opensource.google/gerrit/gerrit/gerrit/+/master:polygerrit-ui/app/utils/path-list-util.ts;l=10;drc=57014d5ba3e0b48e3372e3aa3c67463cb6e56bca
  static specialFilePathCompare(a: string, b: string) {
    const aLastDotIndex = a.lastIndexOf('.');
    const aExt = a.substr(aLastDotIndex + 1);
    const aFile = a.substr(0, aLastDotIndex) || a;

    const bLastDotIndex = b.lastIndexOf('.');
    const bExt = b.substr(bLastDotIndex + 1);
    const bFile = b.substr(0, bLastDotIndex) || b;

    // Sort header files above others with the same base name.
    const headerExts = ['h', 'hh', 'hxx', 'hpp'];
    if (aFile.length > 0 && aFile === bFile) {
      if (headerExts.includes(aExt) && headerExts.includes(bExt)) {
        return a.localeCompare(b);
      }
      if (headerExts.includes(aExt)) {
        return -1;
      }
      if (headerExts.includes(bExt)) {
        return 1;
      }
    }
    return aFile.localeCompare(bFile) || a.localeCompare(b);
  }
}
