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

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

  /**
   * 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 project_config for code owners.
   *
   * @doc https://gerrit.googlesource.com/plugins/code-owners/+/refs/heads/master/resources/Documentation/rest-api.md#get-code-owner-project-config
   * @param {string} project
   */
  getProjectConfig(project) {
    return this.restApi.get(
        `/projects/${encodeURIComponent(project)}/code_owners.project_config`
    );
  }
}

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

    // fetched files and fetching status
    this._fetchedOwners = new Map();
    this._fetchStatus = FetchStatus.NOT_STARTED;
    this._totalFetchCount = 0;

    this.init();
  }

  /**
   * Initial fetches.
   */
  init() {
    this.accountPromise = this.restApi.getLoggedIn().then(loggedIn => {
      if (!loggedIn) {
        return undefined;
      }
      return this.restApi.getAccount();
    });

    this.statusPromise = this.isCodeOwnerEnabled().then(enabled => {
      if (!enabled) {
        return {
          patchsetNumber: 0,
          enabled: false,
          codeOwnerStatusMap: new Map(),
          rawStatuses: [],
        };
      }
      return this.codeOwnerApi
          .listOwnerStatus(this.change._number)
          .then(res => {
            return {
              enabled: true,
              patchsetNumber: res.patch_set_number,
              codeOwnerStatusMap: this._formatStatuses(
                  res.file_code_owner_statuses
              ),
              rawStatuses: res.file_code_owner_statuses,
            };
          });
    });
  }

  /**
   * 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.
   */
  getLoggedInUserInitialRole() {
    return this.accountPromise.then(account => {
      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);
  }

  getStatus() {
    return this.statusPromise.then(res => {
      if (res.enabled && !this.isOnLatestPatchset(res.patchsetNumber)) {
        // status is outdated, abort and re-init
        this.abort();
        this.init();
        return this.statusPromise;
      }
      return res;
    });
  }

  areAllFilesApproved() {
    return this.getStatus().then(({rawStatuses}) => {
      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,
   *  }>
   * }}
   */
  getSuggestedOwners() {
    // 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._fetchStatus === FetchStatus.NOT_STARTED
      || this._fetchStatus === FetchStatus.ABORT) {
      this._fetchSuggestedOwners().then(() => {
        this._fetchStatus = FetchStatus.FINISHED;
      });
    }

    return this.getStatus().then(({codeOwnerStatusMap}) => {
      return {
        finished: this._fetchStatus === FetchStatus.FINISHED,
        status: this._fetchStatus,
        progress: this._totalFetchCount === 0 ?
          `Loading suggested owners ...` :
          `${this._fetchedOwners.size} out of ${this._totalFetchCount} files have returned suggested owners.`,
        suggestions: this._groupFilesByOwners(codeOwnerStatusMap),
      };
    });
  }

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

    return this.getStatus()
        .then(({codeOwnerStatusMap}) => {
          // 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;
          return this._batchFetchCodeOwners(filesToFetch);
        });
  }

  _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) {
    // 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 allFiles = [...this._fetchedOwners.keys()];
    const ownersFilesMap = new Map();
    const failedToFetchFiles = new Set();
    for (let i = 0; i < allFiles.length; i++) {
      const fileInfo = {
        path: allFiles[i],
        status: this._computeFileStatus(codeOwnerStatusMap, allFiles[i]),
      };
      // for files failed to fetch, add them to the special group
      if (this._fetchedOwners.get(fileInfo.path).error) {
        failedToFetchFiles.add(fileInfo);
        continue;
      }

      // do not include files still in fetching
      if (!this._fetchedOwners.get(fileInfo.path).owners) {
        continue;
      }
      const owners = [...this._fetchedOwners.get(fileInfo.path).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}`;
  }

  /**
   * Recursively fetches code owners for all files until finished.
   *
   * @param {!Array<string>} files
   */
  _batchFetchCodeOwners(files) {
    if (this._fetchStatus === FetchStatus.ABORT) {
      return Promise.resolve(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.codeOwnerApi
                .listOwnersForPath(
                    this.change.id,
                    filePath
                )
                .then(owners => {
                  // use Set to de-dup
                  this._fetchedOwners.get(filePath).owners = new Set(owners);
                })
                .catch(e => {
                  this._fetchedOwners.get(filePath).error = e;
                })
        );
      }
    }
    const resPromise = Promise.all(batchRequests);
    if (files.length > maxConcurrentRequests) {
      return resPromise.then(() => {
        return this._batchFetchCodeOwners(files.slice(maxConcurrentRequests));
      });
    }
    return resPromise.then(() => this._fetchedOwners);
  }

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

  getProjectConfig() {
    if (!this.getProjectConfigPromise) {
      this.getProjectConfigPromise =
          this.codeOwnerApi.getProjectConfig(this.change.project);
    }
    return this.getProjectConfigPromise;
  }

  isCodeOwnerEnabled() {
    if (this.change.status === ChangeStatus.ABANDONED ||
        this.change.status === ChangeStatus.MERGED) {
      return Promise.resolve(false);
    }
    return this.getProjectConfig().then(config => {
      if (config.status && config.status.disabled) {
        return false;
      }
      if (config.status
          && config.status.disabled_branches
          && config.status.disabled_branches.includes(this.change.branch)) {
        return false;
      }
      return true;
    });
  }

  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,
      });
    }
    return this.ownerService;
  }
}
