/**
 * @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.
 */

/**
 * All statuses returned for owner status.
 *
 * @enum
 */
export const OwnerStatus = {
  INSUFFICIENT_REVIEWERS: 'INSUFFICIENT_REVIEWERS',
  PENDING: 'PENDING',
  APPROVED: 'APPROVED',
};

/**
 * @enum
 */
const FetchStatus = {
  NOT_STARTED: 0,
  FETCHING: 1,
  FINISHED: 2,
  ABORT: 3,
};

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

/**
 * @enum
 */
const UserRole = {
  ANONYMOUS: 'ANONYMOUS',
  AUTHOR: 'AUTHOR',
  CHANGE_OWNER: 'CHANGE_OWNER',
  REVIEWER: 'REVIEWER',
  CC: 'CC',
  REMOVED_REVIEWER: 'REMOVED_REVIEWER',
  OTHER: 'OTHER',
};

// TODO: Try to remove it. The ResponseError and getErrorMessage duplicates
// code from the gr-plugin-rest-api.ts. This code is required because
// we want custom error processing in some functions. For details see
// the original gr-plugin-rest-api.ts file/

class ResponseError extends Error {
  constructor(response) {
    super();
    this.response = response;
  }
}

async function getErrorMessage(response) {
  const text = await response.text();
  return text ?
    `${response.status}: ${text}` :
    `${response.status}`;
}

/**
 * Responsible for communicating with the rest-api
 *
 * @see resources/Documentation/rest-api.md
 */
class CodeOwnerApi {
  constructor(restApi) {
    this.restApi = restApi;
  }

  /**
   * Returns a promise fetching the owner statuses for all files within the change.
   *
   * @doc https://gerrit.googlesource.com/plugins/code-owners/+/refs/heads/master/resources/Documentation/rest-api.md#change-endpoints
   * @param {string} changeId
   */
  listOwnerStatus(changeId) {
    return this.restApi.get(`/changes/${changeId}/code_owners.status`);
  }

  /**
   * Returns a promise fetching the owners for a given path.
   *
   * @doc https://gerrit.googlesource.com/plugins/code-owners/+/refs/heads/master/resources/Documentation/rest-api.md#list-code-owners-for-path-in-branch
   * @param {string} changeId
   * @param {string} path
   */
  listOwnersForPath(changeId, path) {
    return this.restApi.get(
        `/changes/${changeId}/revisions/current/code_owners` +
        `/${encodeURIComponent(path)}?limit=5&o=DETAILS&resolve-all-users=true`
    );
  }

  /**
   * Returns a promise fetching the owners config for a given path.
   *
   * @doc https://gerrit.googlesource.com/plugins/code-owners/+/refs/heads/master/resources/Documentation/rest-api.md#branch-endpoints
   * @param {string} project
   * @param {string} branch
   * @param {string} path
   */
  getConfigForPath(project, branch, path) {
    return this.restApi.get(
        `/projects/${encodeURIComponent(project)}/` +
        `branches/${encodeURIComponent(branch)}/` +
        `code_owners.config/${encodeURIComponent(path)}`
    );
  }

  /**
   * Returns a promise fetching the owners config for a given branch.
   *
   * @doc https://gerrit.googlesource.com/plugins/code-owners/+/refs/heads/master/resources/Documentation/rest-api.md#branch-endpoints
   * @param {string} project
   * @param {string} branch
   */
  async getBranchConfig(project, branch) {
    const errFn = (response, error) => {
      if (error) throw error;
      if (response) throw new ResponseError(response);
      throw new Error('Generic REST API error');
    }
    try {
      const config = await this.restApi.send(
          'GET',
          `/projects/${encodeURIComponent(project)}/` +
          `branches/${encodeURIComponent(branch)}/` +
          `code_owners.branch_config`,
          undefined,
          errFn
      );
      if (config.override_approval && !(config.override_approval
          instanceof Array)) {
        // In the upcoming backend changes, the override_approval will be changed
        // to array with (possible) multiple items.
        // While this transition is in progress, the frontend supports both API -
        // the old one and the new one.
        return {...config, override_approval: [config.override_approval]};
      }
      return config;
    } catch(err) {
      if (err instanceof ResponseError) {
        if (err.response.status === 404) {
          // The 404 error means that the branch doesn't exist and
          // the plugin should be disabled.
          return {disabled: true};
        }
        return getErrorMessage(err.response).then(msg => {
          throw new Error(msg);
        });
      }
      throw err;
    }
  }
}

/**
 * Wrapper around codeOwnerApi, sends each requests only once and then cache
 * the response. A new CodeOwnersCacheApi instance is created every time when a
 * new change object is assigned.
 * Gerrit never updates existing change object, but instead always assigns a new
 * change object. Particularly, a new change object is assigned when a change
 * is updated and user clicks reload toasts to see the updated change.
 * As a result, the lifetime of a cache is the same as a lifetime of an assigned
 * change object.
 * Periodical cache invalidation can lead to inconsistency in UI, i.e.
 * user can see the old reviewers list (reflects a state when a change was
 * loaded) and code-owners status for the current reviewer list. To avoid
 * this inconsistency, the cache doesn't invalidate.
 */
export class CodeOwnersCacheApi {
  constructor(codeOwnerApi, change) {
    this.codeOwnerApi = codeOwnerApi;
    this.change = change;
    this.promises = {};
  }

  _fetchOnce(cacheKey, asyncFn) {
    if (!this.promises[cacheKey]) {
      this.promises[cacheKey] = asyncFn();
    }
    return this.promises[cacheKey];
  }

  getAccount() {
    return this._fetchOnce('getAccount', () => this._getAccount());
  }

  async _getAccount() {
    const loggedIn = await this.codeOwnerApi.restApi.getLoggedIn();
    if (!loggedIn) return undefined;
    return await this.codeOwnerApi.restApi.getAccount();
  }

  listOwnerStatus() {
    return this._fetchOnce('listOwnerStatus',
        () => this.codeOwnerApi.listOwnerStatus(this.change._number));
  }

  getBranchConfig() {
    return this._fetchOnce('getBranchConfig',
        () => this.codeOwnerApi.getBranchConfig(this.change.project,
            this.change.branch));
  }

  listOwnersForPath(path) {
    return this._fetchOnce(`listOwnersForPath:${path}`,
        () => this.codeOwnerApi.listOwnersForPath(this.change.id, path));
  }
}

export class OwnersFetcher {
  constructor(restApi, change, options) {
    // fetched files and fetching status
    this._fetchedOwners = new Map();
    this._fetchStatus = FetchStatus.NOT_STARTED;
    this._totalFetchCount = 0;
    this.change = change;
    this.options = options;
    this.codeOwnerApi = new CodeOwnerApi(restApi);
  }

  getStatus() {
    return this._fetchStatus;
  }

  getProgressString() {
    return this._totalFetchCount === 0 ?
      `Loading suggested owners ...` :
      `${this._fetchedOwners.size} out of ${this._totalFetchCount} files have returned suggested owners.`;
  }

  getFiles() {
    const result = [];
    for (const [path, info] of this._fetchedOwners.entries()) {
      result.push({path, info});
    }
    return result;
  }

  async fetchSuggestedOwners(codeOwnerStatusMap) {
    // reset existing temporary storage
    this._fetchedOwners = new Map();
    this._fetchStatus = FetchStatus.FETCHING;
    this._totalFetchCount = 0;

    // only fetch those not approved yet
    const filesGroupByStatus = [...codeOwnerStatusMap.keys()].reduce(
        (list, file) => {
          const status = codeOwnerStatusMap
              .get(file).status;
          if (status === OwnerStatus.INSUFFICIENT_REVIEWERS) {
            list.missing.push(file);
          } else if (status === OwnerStatus.PENDING) {
            list.pending.push(file);
          }
          return list;
        }
        , {pending: [], missing: []});
    // always fetch INSUFFICIENT_REVIEWERS first and then pending
    const filesToFetch = filesGroupByStatus.missing
        .concat(filesGroupByStatus.pending);
    this._totalFetchCount = filesToFetch.length;
    await this._batchFetchCodeOwners(filesToFetch);
    this._fetchStatus = FetchStatus.FINISHED;
  }

  /**
   * Recursively fetches code owners for all files until finished.
   *
   * @param {!Array<string>} files
   */
  async _batchFetchCodeOwners(files) {
    if (this._fetchStatus === FetchStatus.ABORT) {
      return this._fetchedOwners;
    }

    const batchRequests = [];
    const maxConcurrentRequests = this.options.maxConcurrentRequests;
    for (let i = 0; i < maxConcurrentRequests; i++) {
      const filePath = files[i];
      if (filePath) {
        this._fetchedOwners.set(filePath, {});
        batchRequests.push(this._fetchOwnersForPath(this.change.id, filePath));
      }
    }
    const resPromise = Promise.all(batchRequests);
    await resPromise;
    if (files.length > maxConcurrentRequests) {
      return await this._batchFetchCodeOwners(
          files.slice(maxConcurrentRequests));
    }
    return this._fetchedOwners;
  }

  async _fetchOwnersForPath(changeId, filePath) {
    try {
      const owners = await this.codeOwnerApi.listOwnersForPath(changeId,
          filePath);
      // In the upcoming backend changes, the api will return an object instead
      // of array. While this transition is in progress, the frontend supports
      // both API - the old one and the new one.
      this._fetchedOwners.get(filePath).owners = new Set(
          owners instanceof Array ? owners : owners.code_owners);
    } catch (e) {
      this._fetchedOwners.get(filePath).error = e;
    }
  }

  abort() {
    this._fetchStatus = FetchStatus.ABORT;
    this._fetchedOwners = new Map();
    this._totalFetchCount = 0;
  }
}

/**
 * Service for the data layer used in the plugin UI.
 */
export class CodeOwnerService {
  constructor(restApi, change, options = {}) {
    this.restApi = restApi;
    this.change = change;
    const codeOwnerApi = new CodeOwnerApi(restApi);
    this.codeOwnerCacheApi = new CodeOwnersCacheApi(codeOwnerApi, change);

    const fetcherOptions = {
      maxConcurrentRequests: options.maxConcurrentRequests || 10,
    };
    this.ownersFetcher = new OwnersFetcher(restApi, change, fetcherOptions);
  }

  /**
   * Prefetch data
   */
  async prefetch() {
    try {
      await Promise.all([
        this.codeOwnerCacheApi.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() {
    const account = await this.codeOwnerCacheApi.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;
  }

  _accountInReviewers(reviewers, account) {
    if (!reviewers) {
      return false;
    }
    return reviewers.some(reviewer =>
      reviewer._account_id === account._account_id);
  }

  async getStatus() {
    const status = await this._getStatus();
    if (status.enabled && !this.isOnLatestPatchset(status.patchsetNumber)) {
      // status is outdated, abort and re-init
      this.abort();
      this.prefetch();
      return await this.codeOwnerCacheApi.getStatus();
    }
    return status;
  }

  async _getStatus() {
    const enabled = await this.isCodeOwnerEnabled();
    if (!enabled) {
      return {
        patchsetNumber: 0,
        enabled: false,
        codeOwnerStatusMap: new Map(),
        rawStatuses: [],
      };
    }

    const onwerStatus = await this.codeOwnerCacheApi.listOwnerStatus();

    return {
      enabled: true,
      patchsetNumber: onwerStatus.patch_set_number,
      codeOwnerStatusMap: this._formatStatuses(
          onwerStatus.file_code_owner_statuses
      ),
      rawStatuses: onwerStatus.file_code_owner_statuses,
    };
  }

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

  /**
   * Gets owner suggestions.
   *
   * @returns {{
   *  finished?: boolean,
   *  progress?: string,
   *  suggestions: Array<{
   *    groupName: {
   *      name: string,
   *      prefix: string
   *    },
   *    error?: Error,
   *    owners?: Array,
   *    files: Array,
   *  }>
   * }}
   */
  async getSuggestedOwners() {
    const {codeOwnerStatusMap} = await this.getStatus();

    // In case its aborted due to outdated patches
    // should kick start the fetching again
    // Note: we currently are not reusing the instance when switching changes,
    // so if its `abort` due to different changes, the whole instance will be
    // outdated and not used.
    if (this.ownersFetcher.getStatus() === FetchStatus.NOT_STARTED
      || this.ownersFetcher.getStatus() === FetchStatus.ABORT) {
      await this.ownersFetcher.fetchSuggestedOwners(codeOwnerStatusMap);
    }

    return {
      finished: this.ownersFetcher.getStatus() === FetchStatus.FINISHED,
      status: this.ownersFetcher.getStatus(),
      progress: this.ownersFetcher.getProgressString(),
      suggestions: this._groupFilesByOwners(codeOwnerStatusMap,
          this.ownersFetcher.getFiles()),
    };
  }

  async getSuggestedOwnersProgress() {
    const {codeOwnerStatusMap} = await this.getStatus();
    return {
      finished: this.ownersFetcher.getStatus() === FetchStatus.FINISHED,
      status: this.ownersFetcher.getStatus(),
      progress: this.ownersFetcher.getProgressString(),
      suggestions: this._groupFilesByOwners(codeOwnerStatusMap,
          this.ownersFetcher.getFiles()),
    };
  }

  _formatStatuses(statuses) {
    // 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,
        });
      }
      if (newPathStatus) {
        prev.set(newPathStatus.path, {
          changeType: cur.change_type,
          status: newPathStatus.status,
          oldPath: oldPathStatus ? oldPathStatus.path : null,
        });
      }
      return prev;
    }, new Map());
  }

  _computeFileStatus(fileStatusMap, path) {
    // empty for modified files and old-name files
    // Show `Renamed` for renamed file
    const status = fileStatusMap.get(path);
    if (status.oldPath) {
      return 'Renamed';
    }
    return;
  }

  _groupFilesByOwners(codeOwnerStatusMap, files) {
    // Note: for renamed or moved files, they will have two entries in the map
    // we will treat them as two entries when group as well
    const ownersFilesMap = new Map();
    const failedToFetchFiles = new Set();
    for (const file of files) {
      const fileInfo = {
        path: file.path,
        status: this._computeFileStatus(codeOwnerStatusMap, file.path),
      };
      // for files failed to fetch, add them to the special group
      if (file.info.error) {
        failedToFetchFiles.add(fileInfo);
        continue;
      }

      // do not include files still in fetching
      if (!file.info.owners) {
        continue;
      }
      const owners = [...file.info.owners];
      const ownersKey = owners
          .map(owner => owner.account._account_id)
          .sort()
          .join(',');
      ownersFilesMap.set(
          ownersKey,
          ownersFilesMap.get(ownersKey) || {files: [], owners}
      );
      ownersFilesMap.get(ownersKey).files.push(fileInfo);
    }
    const groupedItems = [];
    for (const ownersKey of ownersFilesMap.keys()) {
      const groupName = this.getGroupName(ownersFilesMap.get(ownersKey).files);
      groupedItems.push({
        groupName,
        files: ownersFilesMap.get(ownersKey).files,
        owners: ownersFilesMap.get(ownersKey).owners,
      });
    }

    if (failedToFetchFiles.size > 0) {
      const failedFiles = [...failedToFetchFiles];
      groupedItems.push({
        groupName: this.getGroupName(failedFiles),
        files: failedFiles,
        error: new Error(
            'Failed to fetch code owner info. Try to refresh the page.'),
      });
    }

    return groupedItems;
  }

  getGroupName(files) {
    const fileName = files[0].path.split('/').pop();
    return {
      name: fileName,
      prefix: files.length > 1 ? `+ ${files.length - 1} more` : '',
    };
  }

  isOnLatestPatchset(patchsetId) {
    const latestRevision = this.change.revisions[this.change.current_revision];
    return `${latestRevision._number}` === `${patchsetId}`;
  }

  abort() {
    this.ownersFetcher.abort();
    const codeOwnerApi = new CodeOwnerApi(this.restApi);
    this.codeOwnerCacheApi = new CodeOwnersCacheApi(codeOwnerApi, change);
  }

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

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

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

