/**
 * @license
 * Copyright 2020 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import {
  BasePatchSetNum,
  ChangeInfo,
  EditInfo,
  EDIT,
  PARENT,
  NumericChangeId,
  PatchSetNum,
  PreferencesInfo,
  RevisionPatchSetNum,
  PatchSetNumber,
  CommitId,
  RevisionInfo,
} from '../../types/common';
import {ChangeStatus, DefaultBase} from '../../constants/constants';
import {combineLatest, from, Observable, forkJoin, of} from 'rxjs';
import {
  map,
  filter,
  withLatestFrom,
  switchMap,
  catchError,
} from 'rxjs/operators';
import {
  computeAllPatchSets,
  computeLatestPatchNum,
  computeLatestPatchNumWithEdit,
  findEdit,
  sortRevisions,
} from '../../utils/patch-set-util';
import {isDefined, LoadingStatus, ParsedChangeInfo} from '../../types/types';
import {fireAlert, fireTitleChange} from '../../utils/event-util';
import {RestApiService} from '../../services/gr-rest-api/gr-rest-api';
import {select} from '../../utils/observable-util';
import {assertIsDefined} from '../../utils/common-util';
import {Model} from '../base/model';
import {UserModel} from '../user/user-model';
import {define} from '../dependency';
import {isOwner} from '../../utils/change-util';
import {
  ChangeChildView,
  ChangeViewModel,
  createChangeUrl,
} from '../views/change';
import {NavigationService} from '../../elements/core/gr-navigation/gr-navigation';
import {getRevertCreatedChangeIds} from '../../utils/message-util';
import {computeTruncatedPath} from '../../utils/path-list-util';
import {PluginLoader} from '../../elements/shared/gr-js-api-interface/gr-plugin-loader';
import {ReportingService} from '../../services/gr-reporting/gr-reporting';
import {Timing} from '../../constants/reporting';

const ERR_REVIEW_STATUS = 'Couldn’t change file review status.';

export interface ChangeState {
  /**
   * If `change` is undefined, this must be either NOT_LOADED or LOADING.
   * If `change` is defined, this must be either LOADED.
   */
  loadingStatus: LoadingStatus;
  change?: ParsedChangeInfo;
  /**
   * The list of reviewed files, kept in the model because we want changes made
   * in one view to reflect on other views without re-rendering the other views.
   * Undefined means it's still loading and empty set means no files reviewed.
   */
  reviewedFiles?: string[];
  /**
   * Either filled from `change.mergeable`, or from a dedicated REST API call.
   * Is initially `undefined`, such that you can identify whether this
   * information has already been loaded once for this change or not. Will never
   * go back to `undefined` after being set for a change.
   */
  mergeable?: boolean;
}

/**
 * `change.revisions` is a dictionary mapping the revision sha to RevisionInfo,
 * but the info object itself does not contain the sha, which is a problem when
 * working with just the info objects.
 *
 * So we are iterating over the map here and are assigning the sha map key to
 * the property `revision.commit.commit`.
 *
 * As usual we are treating data objects as immutable, so we are doind a lot of
 * cloning here.
 */
export function updateRevisionsWithCommitShas(changeInput?: ParsedChangeInfo) {
  if (!changeInput?.revisions) return changeInput;
  const changeOutput = {...changeInput, revisions: {...changeInput.revisions}};
  for (const sha of Object.keys(changeOutput.revisions)) {
    const revision = changeOutput.revisions[sha];
    if (revision?.commit && !revision.commit.commit) {
      changeOutput.revisions[sha] = {
        ...revision,
        commit: {...revision.commit, commit: sha as CommitId},
      };
    }
  }
  return changeOutput;
}

/**
 * Updates the change object with information from the saved `edit` patchset.
 */
// visible for testing
export function updateChangeWithEdit(
  change?: ParsedChangeInfo,
  edit?: EditInfo,
  viewModelPatchNum?: PatchSetNum
): ParsedChangeInfo | undefined {
  if (!change || !edit) return change;
  assertIsDefined(edit.commit.commit, 'edit.commit.commit');
  if (!change.revisions) change.revisions = {};
  change.revisions[edit.commit.commit] = {
    _number: EDIT,
    basePatchNum: edit.base_patch_set_number,
    commit: edit.commit,
    fetch: edit.fetch,
  };
  // If the change was loaded without a specific patchset, then this normally
  // means that the *latest* patchset should be loaded. But if there is an
  // active edit, then automatically switch to that edit as the current
  // patchset.
  // TODO: This goes together with `_patchRange.patchNum' being set to `edit`,
  // which is still done in change-view. `_patchRange.patchNum` should
  // eventually also be model managed, so we can reconcile these two code
  // snippets into one location.
  if (viewModelPatchNum === undefined) {
    change.current_revision = edit.commit.commit;
  }
  return change;
}

/**
 * Derives the base patchset number from all the data that can potentially
 * influence it. Mostly just returns `viewModelBasePatchNum` or PARENT, but has
 * some special logic when looking at merge commits.
 *
 * NOTE: At the moment this returns just `viewModelBasePatchNum ?? PARENT`, see
 * TODO below.
 */
function computeBase(
  viewModelBasePatchNum: BasePatchSetNum | undefined,
  patchNum: RevisionPatchSetNum | undefined,
  change: ParsedChangeInfo | undefined,
  preferences: PreferencesInfo
): BasePatchSetNum {
  if (viewModelBasePatchNum && viewModelBasePatchNum !== PARENT) {
    return viewModelBasePatchNum;
  }
  if (!change || !patchNum) return PARENT;

  const preferFirst =
    preferences.default_base_for_merges === DefaultBase.FIRST_PARENT;
  if (!preferFirst) return PARENT;

  // TODO: Re-enable respecting the default_base_for_merges preference.
  // For the Polygerrit UI this was originally implemented in change 214432,
  // but we are not sure whether this was ever 100% working correctly. A
  // major challenge is being able to select PARENT explicitly even if your
  // preference for the default choice is FIRST_PARENT. <gr-file-list-header>
  // just uses `navigation.setUrl()` and the view model does not have any
  // way of forcing the basePatchSetNum to stick to PARENT without being
  // altered back to FIRST_PARENT here.
  // See also corresponding TODO in gr-settings-view.
  return PARENT;
  // const revisionInfo = new RevisionInfo(change);
  // const isMergeCommit = revisionInfo.isMergeCommit(patchNum);
  // return isMergeCommit ? (-1 as PatchSetNumber) : PARENT;
}

// TODO: Figure out how to best enforce immutability of all states. Use Immer?
// Use DeepReadOnly?
const initialState: ChangeState = {
  loadingStatus: LoadingStatus.NOT_LOADED,
};

export const changeModelToken = define<ChangeModel>('change-model');
/**
 * Change model maintains information about the current change.
 *
 * The "current" change is defined by ChangeViewModel. This model tracks part of
 * the current view. As such it's a singleton global state. It's NOT meant to
 * keep the state of an arbitrary change.
 */
export class ChangeModel extends Model<ChangeState> {
  private change?: ParsedChangeInfo;

  private patchNum?: RevisionPatchSetNum;

  private basePatchNum?: BasePatchSetNum;

  private latestPatchNum?: PatchSetNumber;

  public readonly change$ = select(
    this.state$,
    changeState => changeState.change
  );

  public readonly changeLoadingStatus$ = select(
    this.state$,
    changeState => changeState.loadingStatus
  );

  public readonly loading$ = select(
    this.changeLoadingStatus$,
    status => status === LoadingStatus.LOADING
  );

  public readonly reviewedFiles$ = select(
    this.state$,
    changeState => changeState?.reviewedFiles
  );

  public readonly mergeable$ = select(
    this.state$,
    changeState => changeState.mergeable
  );

  public readonly branch$ = select(this.change$, change => change?.branch);

  public readonly changeNum$ = select(this.change$, change => change?._number);

  public readonly changeId$ = select(this.change$, change => change?.change_id);

  public readonly repo$ = select(this.change$, change => change?.project);

  public readonly topic$ = select(this.change$, change => change?.topic);

  public readonly status$ = select(this.change$, change => change?.status);

  public readonly labels$ = select(this.change$, change => change?.labels);

  public readonly revisions$ = select(this.change$, change =>
    sortRevisions(Object.values(change?.revisions || {}))
  );

  public readonly patchsets$ = select(this.change$, change =>
    computeAllPatchSets(change)
  );

  public readonly latestPatchNum$ = select(this.patchsets$, patchsets =>
    computeLatestPatchNum(patchsets)
  );

  public readonly latestPatchNumWithEdit$ = select(this.patchsets$, patchsets =>
    computeLatestPatchNumWithEdit(patchsets)
  );

  public readonly latestUploader$ = select(
    this.change$,
    change => change?.revisions[change.current_revision]?.uploader
  );

  public readonly latestCommitter$ = select(
    this.change$,
    change => change?.revisions[change.current_revision]?.commit?.committer
  );

  /**
   * Emits the current patchset number. If the route does not define the current
   * patchset num, then this selector waits for the change to be defined and
   * returns the number of the latest patchset.
   *
   * Note that this selector can emit without the change being available!
   */
  public readonly patchNum$: Observable<RevisionPatchSetNum | undefined> =
    select(
      combineLatest([
        this.viewModel.state$,
        this.state$,
        this.latestPatchNumWithEdit$,
      ]).pipe(
        /**
         * If you depend on both, view model and change state, then you want to
         * filter out inconsistent state, e.g. view model changeNum already
         * updated, change not yet reset to undefined.
         */
        filter(([viewModelState, changeState, _latestPatchN]) => {
          const changeNum = changeState.change?._number;
          const viewModelChangeNum = viewModelState?.changeNum;
          return changeNum === undefined || changeNum === viewModelChangeNum;
        })
      ),
      ([viewModelState, _changeState, latestPatchN]) =>
        viewModelState?.patchNum || latestPatchN
    );

  /** The user can enter edit mode without an `EDIT` patchset existing yet. */
  public readonly editMode$ = select(
    combineLatest([this.viewModel.edit$, this.patchNum$]),
    ([edit, patchNum]) => !!edit || patchNum === EDIT
  );

  /**
   * Emits the base patchset number. This is identical to the
   * `viewModel.basePatchNum$`, but has some special logic for merges.
   *
   * Note that this selector can emit without the change being available!
   */
  public readonly basePatchNum$: Observable<BasePatchSetNum> =
    /**
     * If you depend on both, view model and change state, then you want to
     * filter out inconsistent state, e.g. view model changeNum already
     * updated, change not yet reset to undefined.
     */
    select(
      combineLatest([
        this.viewModel.state$,
        this.state$,
        this.userModel.state$,
      ]).pipe(
        filter(([viewModelState, changeState, _]) => {
          const changeNum = changeState.change?._number;
          const viewModelChangeNum = viewModelState?.changeNum;
          return changeNum === undefined || changeNum === viewModelChangeNum;
        }),
        withLatestFrom(
          this.viewModel.basePatchNum$,
          this.patchNum$,
          this.change$,
          this.userModel.preferences$
        )
      ),
      ([_, viewModelBasePatchNum, patchNum, change, preferences]) =>
        computeBase(viewModelBasePatchNum, patchNum, change, preferences)
    );

  private selectRevision(
    revisionNum$: Observable<RevisionPatchSetNum | BasePatchSetNum | undefined>
  ) {
    return select(
      combineLatest([this.revisions$, revisionNum$]),
      ([revisions, patchNum]) => {
        if (!revisions || !patchNum || patchNum === PARENT) return undefined;
        return Object.values(revisions).find(
          revision => revision._number === patchNum
        );
      }
    );
  }

  public readonly revision$ = this.selectRevision(this.patchNum$);

  public readonly baseRevision$ = this.selectRevision(
    this.basePatchNum$
  ) as Observable<RevisionInfo | undefined>;

  public readonly latestRevision$ = this.selectRevision(this.latestPatchNum$);

  public readonly isOwner$: Observable<boolean> = select(
    combineLatest([this.change$, this.userModel.account$]),
    ([change, account]) => isOwner(change, account)
  );

  public readonly messages$ = select(this.change$, change => change?.messages);

  public readonly revertingChangeIds$ = select(this.messages$, messages =>
    getRevertCreatedChangeIds(messages ?? [])
  );

  constructor(
    private readonly navigation: NavigationService,
    private readonly viewModel: ChangeViewModel,
    private readonly restApiService: RestApiService,
    private readonly userModel: UserModel,
    private readonly pluginLoader: PluginLoader,
    private readonly reporting: ReportingService
  ) {
    super(initialState);
    this.subscriptions = [
      this.loadChange(),
      this.loadMergeable(),
      this.loadReviewedFiles(),
      this.setOverviewTitle(),
      this.setDiffTitle(),
      this.setEditTitle(),
      this.reportChangeReload(),
      this.fireShowChange(),
      this.refuseEditForOpenChange(),
      this.refuseEditForClosedChange(),
      this.change$.subscribe(change => (this.change = change)),
      this.patchNum$.subscribe(patchNum => (this.patchNum = patchNum)),
      this.basePatchNum$.subscribe(
        basePatchNum => (this.basePatchNum = basePatchNum)
      ),
      this.latestPatchNum$.subscribe(
        latestPatchNum => (this.latestPatchNum = latestPatchNum)
      ),
    ];
  }

  private reportChangeReload() {
    return this.changeLoadingStatus$.subscribe(loadingStatus => {
      if (loadingStatus === LoadingStatus.LOADING) {
        this.reporting.time(Timing.CHANGE_RELOAD);
      }
      if (
        loadingStatus === LoadingStatus.LOADED ||
        loadingStatus === LoadingStatus.NOT_LOADED
      ) {
        this.reporting.timeEnd(Timing.CHANGE_RELOAD);
      }
    });
  }

  private fireShowChange() {
    return combineLatest([
      this.change$,
      this.basePatchNum$,
      this.patchNum$,
      this.mergeable$,
    ])
      .pipe(
        filter(
          ([change, basePatchNum, patchNum, mergeable]) =>
            !!change && !!basePatchNum && !!patchNum && mergeable !== undefined
        )
      )
      .subscribe(([change, basePatchNum, patchNum, mergeable]) => {
        this.pluginLoader.jsApiService.handleShowChange({
          change,
          basePatchNum,
          patchNum,
          // `?? null` is for the TypeScript compiler only. We have a
          // `mergeable !== undefined` filter above, so this cannot happen.
          // It would be nice to change `ShowChangeDetail` to accept `undefined`
          // instaed of `null`, but that would be a Plugin API change ...
          info: {mergeable: mergeable ?? null},
        });
      });
  }

  private refuseEditForOpenChange() {
    return combineLatest([this.revisions$, this.patchNum$, this.status$])
      .pipe(
        filter(
          ([revisions, patchNum, status]) =>
            status === ChangeStatus.NEW &&
            revisions.length > 0 &&
            patchNum === EDIT
        )
      )
      .subscribe(([revisions]) => {
        const editRev = findEdit(revisions);
        if (!editRev) {
          const msg = 'Change edit not found. Please create a change edit.';
          fireAlert(document, msg);
          this.navigateToChangeResetReload();
        }
      });
  }

  private refuseEditForClosedChange() {
    return combineLatest([
      this.revisions$,
      this.viewModel.edit$,
      this.patchNum$,
      this.status$,
    ])
      .pipe(
        filter(
          ([revisions, edit, patchNum, status]) =>
            (status === ChangeStatus.ABANDONED ||
              status === ChangeStatus.MERGED) &&
            revisions.length > 0 &&
            (patchNum === EDIT || edit)
        )
      )
      .subscribe(([revisions]) => {
        const editRev = findEdit(revisions);
        if (!editRev) {
          const msg =
            'Change edits cannot be created if change is merged ' +
            'or abandoned. Redirecting to non edit mode.';
          fireAlert(document, msg);
          this.navigateToChangeResetReload();
        }
      });
  }

  private setOverviewTitle() {
    return combineLatest([this.viewModel.childView$, this.change$])
      .pipe(
        filter(([childView, _]) => childView === ChangeChildView.OVERVIEW),
        map(([_, change]) => change),
        filter(isDefined)
      )
      .subscribe(change => {
        const title = `${change.subject} (${change._number})`;
        fireTitleChange(title);
      });
  }

  private setDiffTitle() {
    return combineLatest([this.viewModel.childView$, this.viewModel.diffPath$])
      .pipe(
        filter(([childView, _]) => childView === ChangeChildView.DIFF),
        map(([_, diffPath]) => diffPath),
        filter(isDefined)
      )
      .subscribe(diffPath => {
        const title = computeTruncatedPath(diffPath);
        fireTitleChange(title);
      });
  }

  private setEditTitle() {
    return combineLatest([this.viewModel.childView$, this.viewModel.editPath$])
      .pipe(
        filter(([childView, _]) => childView === ChangeChildView.EDIT),
        map(([_, editPath]) => editPath),
        filter(isDefined)
      )
      .subscribe(editPath => {
        const title = `Editing ${computeTruncatedPath(editPath)}`;
        fireTitleChange(title);
      });
  }

  private loadReviewedFiles() {
    return combineLatest([
      this.patchNum$,
      this.changeNum$,
      this.userModel.loggedIn$,
    ])
      .pipe(
        switchMap(([patchNum, changeNum, loggedIn]) => {
          if (!changeNum || !patchNum || !loggedIn) {
            this.updateStateReviewedFiles([]);
            return of(undefined);
          }
          return from(this.fetchReviewedFiles(patchNum, changeNum));
        })
      )
      .subscribe();
  }

  private loadMergeable() {
    return this.change$
      .pipe(
        switchMap(change => {
          if (change?._number === undefined) return of(undefined);
          if (change.mergeable !== undefined) return of(change.mergeable);
          if (change.status === ChangeStatus.MERGED) return of(false);
          if (change.status === ChangeStatus.ABANDONED) return of(false);
          return from(
            this.restApiService
              .getMergeable(change._number)
              .then(mergableInfo => mergableInfo?.mergeable ?? false)
          );
        })
      )
      .subscribe(mergeable => this.updateState({mergeable}));
  }

  private loadChange() {
    return this.viewModel.changeNum$
      .pipe(
        switchMap(changeNum => {
          this.updateStateLoading(changeNum);
          // if changeNum is undefined restApi calls return undefined.
          const change = this.restApiService.getChangeDetail(changeNum);
          const edit = this.restApiService.getChangeEdit(changeNum);
          return forkJoin([change, edit]);
        }),
        withLatestFrom(this.viewModel.patchNum$),
        map(([[change, edit], patchNum]) =>
          updateChangeWithEdit(change, edit, patchNum)
        ),
        catchError(err => {
          // Reset loading state and re-throw.
          this.updateState({loadingStatus: LoadingStatus.NOT_LOADED});
          throw err;
        })
      )
      .subscribe(change => {
        // The change service is currently a singleton, so we have to be
        // careful to avoid situations where the application state is
        // partially set for the old change where the user is coming from,
        // and partially for the new change where the user is navigating to.
        // So setting the change explicitly to undefined when the user
        // moves away from diff and change pages (changeNum === undefined)
        // helps with that.
        this.updateStateChange(change ?? undefined);
      });
  }

  updateStateReviewedFiles(reviewedFiles: string[]) {
    this.updateState({reviewedFiles});
  }

  updateStateFileReviewed(file: string, reviewed: boolean) {
    const current = this.getState();
    if (current.reviewedFiles === undefined) {
      // Reviewed files haven't loaded yet.
      // TODO(dhruvsri): disable updating status if reviewed files are not loaded.
      fireAlert(
        document,
        'Updating status failed. Reviewed files not loaded yet.'
      );
      return;
    }
    const reviewedFiles = [...current.reviewedFiles];

    // File is already reviewed and is being marked reviewed
    if (reviewedFiles.includes(file) && reviewed) return;
    // File is not reviewed and is being marked not reviewed
    if (!reviewedFiles.includes(file) && !reviewed) return;

    if (reviewed) reviewedFiles.push(file);
    else reviewedFiles.splice(reviewedFiles.indexOf(file), 1);
    this.updateState({reviewedFiles});
  }

  fetchReviewedFiles(patchNum: PatchSetNum, changeNum: NumericChangeId) {
    return this.restApiService
      .getReviewedFiles(changeNum, patchNum)
      .then(files => {
        if (changeNum !== this.change?._number || patchNum !== this.patchNum)
          return;
        this.updateStateReviewedFiles(files ?? []);
      });
  }

  setReviewedFilesStatus(
    changeNum: NumericChangeId,
    patchNum: PatchSetNum,
    file: string,
    reviewed: boolean
  ) {
    return this.restApiService
      .saveFileReviewed(changeNum, patchNum, file, reviewed)
      .then(() => {
        if (changeNum !== this.change?._number || patchNum !== this.patchNum)
          return;
        this.updateStateFileReviewed(file, reviewed);
      })
      .catch(() => {
        fireAlert(document, ERR_REVIEW_STATUS);
      });
  }

  /**
   * Typically you would just subscribe to change$ yourself to get updates. But
   * sometimes it is nice to also be able to get the current ChangeInfo on
   * demand. So here it is for your convenience.
   */
  getChange() {
    return this.getState().change;
  }

  navigateToDiff(
    diffView: {path: string; lineNum?: number},
    patchNum = this.patchNum,
    basePatchNum = this.basePatchNum
  ) {
    if (!patchNum) return;
    const url = this.viewModel.diffUrl({diffView, patchNum, basePatchNum});
    if (!url) return;
    this.navigation.setUrl(url);
  }

  changeUrl(openReplyDialog = false) {
    if (!this.change) return;
    const isLatest = this.latestPatchNum === this.patchNum;
    return createChangeUrl({
      change: this.change,
      patchNum:
        isLatest && this.basePatchNum === PARENT ? undefined : this.patchNum,
      basePatchNum: this.basePatchNum,
      openReplyDialog,
    });
  }

  // Mainly used for navigating from DIFF to OVERVIEW.
  navigateToChange(openReplyDialog = false) {
    const url = this.changeUrl(openReplyDialog);
    if (!url) return;
    this.navigation.setUrl(url);
  }

  /**
   * Wipes all URL parameters and other view state and goes to the change
   * overview page, forcing a reload.
   *
   * This will also wipe the `patchNum`, so will always go to the latest
   * patchset.
   */
  navigateToChangeResetReload() {
    if (!this.change) return;
    const url = createChangeUrl({change: this.change, forceReload: true});
    if (!url) return;
    this.navigation.setUrl(url);
  }

  navigateToEdit(editView: {path: string; lineNum?: number}) {
    if (!this.patchNum) return;
    const url = this.viewModel.editUrl({editView, patchNum: this.patchNum});
    if (!url) return;
    this.navigation.setUrl(url);
  }

  /**
   * Check whether there is no newer patch than the latest patch that was
   * available when this change was loaded.
   *
   * @return A promise that yields true if the latest patch
   *     has been loaded, and false if a newer patch has been uploaded in the
   *     meantime. The promise is rejected on network error.
   */
  async fetchChangeUpdates(change: ChangeInfo | ParsedChangeInfo) {
    const knownLatest = change.current_revision_number;
    const detail = await this.restApiService.getChange(change._number);
    if (!detail) {
      throw new Error('Change request failed.');
    }
    const actualLatest = detail.current_revision_number;
    return {
      isLatest: actualLatest <= knownLatest,
      newStatus: change.status !== detail.status ? detail.status : null,
      newMessages:
        (change.messages || []).length < (detail.messages || []).length
          ? detail.messages![detail.messages!.length - 1]
          : undefined,
    };
  }

  /**
   * Called when change detail loading is initiated.
   *
   * We want to set the state to LOADING, but we also want to set the change to
   * undefined right away. Otherwise components could see inconsistent state:
   * a new change number, but an old change.
   */
  private updateStateLoading(changeNum?: NumericChangeId) {
    this.updateState({
      change: undefined,
      loadingStatus: changeNum
        ? LoadingStatus.LOADING
        : LoadingStatus.NOT_LOADED,
    });
  }

  // Private but used in tests.
  /**
   * Update the change information in the state.
   *
   * Since the ChangeModel must maintain consistency with ChangeViewModel
   * The update is only allowed, if the new change has the same number as the
   * current change or if the current change is not set (it was reset to
   * undefined when ChangeViewModel.changeNum updated).
   */
  updateStateChange(change?: ParsedChangeInfo) {
    if (this.change && change?._number !== this.change?._number) {
      return;
    }
    change = updateRevisionsWithCommitShas(change);
    this.updateState({
      change,
      loadingStatus:
        change === undefined ? LoadingStatus.NOT_LOADED : LoadingStatus.LOADED,
    });
  }
}
