/**
 * @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;
}

function noAwait(_promise: Promise<unknown>) {}

/**
 * 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();
      noAwait(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),
      };
    });
  }

  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;
  }
}
