/**
 * @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 {BehaviorSubject, Observable} from 'rxjs';
import {type ChangeInfo} from '@gerritcodereview/typescript-api/rest-api';
import {
  ChangeType,
  CodeOwnerBranchConfigInfo,
  FetchedFile,
  FileCodeOwnerStatusInfo,
  OwnerStatus,
  OwnedPathsInfo,
} from './code-owners-api';
import {deepEqual} from './deep-util';
import {select} from './observable-util';

export enum SuggestionsState {
  NotLoaded = 'NotLoaded',
  Loaded = 'Loaded',
  Loading = 'Loading',
  LoadFailed = 'LoadFailed',
}

export enum PluginState {
  Enabled = 'Enabled',
  Disabled = 'Disabled',
  ServerConfigurationError = 'ServerConfigurationError',
  Failed = 'Failed',
}

export interface PluginStatus {
  state: PluginState;
  failedMessage?: string;
}

export function isPluginErrorState(state: PluginState) {
  return (
    state === PluginState.ServerConfigurationError ||
    state === PluginState.Failed
  );
}

export enum SuggestionsType {
  BEST_SUGGESTIONS = 'BEST_SUGGESTIONS',
  ALL_SUGGESTIONS = 'ALL_SUGGESTIONS',
}

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

export interface Suggestion {
  files?: Array<FetchedFile>;
  state: SuggestionsState;
  loadProgress?: string;
}

export interface Status {
  patchsetNumber: number;
  enabled: boolean;
  codeOwnerStatusMap: Map<string, FileStatus>;
  rawStatuses: Array<FileCodeOwnerStatusInfo>;
  newerPatchsetUploaded: boolean;
}

export interface FileStatus {
  changeType: ChangeType;
  status: OwnerStatus;
  newPath?: string | null;
  oldPath?: string | null;
}

export const BestSuggestionsLimit = 5;
export const AllSuggestionsLimit = 1000;

let codeOwnersModel: CodeOwnersModel | undefined;

export interface OwnedPathsInfoOpt {
  oldPaths: Set<string>;
  newPaths: Set<string>;
}

export interface CodeOwnersState {
  showSuggestions: boolean;
  selectedSuggestionsType: SuggestionsType;
  suggestionsByTypes: Map<SuggestionsType, Suggestion>;
  pluginStatus?: PluginStatus;
  branchConfig?: CodeOwnerBranchConfigInfo;
  ownedPaths?: OwnedPathsInfoOpt;
  userRole?: UserRole;
  areAllFilesApproved?: boolean;
  status?: Status;
}

/**
 * Maintain the state of code-owners.
 * Raises 'model-property-changed' event when a property is changed.
 * The plugin shares the same model between all UI elements (if it is not,
 * the plugin can't maintain showSuggestions state across different UI
 * elements). UI elements use values from this model to display information and
 * listens for the model-property-changed event. To do so, UI elements add
 * CodeOwnersModelMixin, which is doing the listening and the translation from
 * model-property-changed event to Polymer property-changed-event. The
 * translation allows to use model properties in observables, bindings,
 * computed properties, etc...
 * The CodeOwnersModelLoader updates the model.
 *
 * It would be good to use RxJs Observable for implementing model properties.
 * However, RxJs library is imported by Gerrit and there is no
 * good way to reuse the same library in the plugin.
 */
export class CodeOwnersModel extends EventTarget {
  private subject$: BehaviorSubject<CodeOwnersState> = new BehaviorSubject({
    showSuggestions: false,
    selectedSuggestionsType: SuggestionsType.BEST_SUGGESTIONS,
    suggestionsByTypes: new Map(),
  } as CodeOwnersState);

  public state$: Observable<CodeOwnersState> = this.subject$.asObservable();

  public showSuggestions$ = select(this.state$, state => state.showSuggestions);

  public selectedSuggestionsType$ = select(
    this.state$,
    state => state.selectedSuggestionsType
  );

  public selectedSuggestionsFiles$ = select(
    this.state$,
    state => state.suggestionsByTypes.get(state.selectedSuggestionsType)?.files
  );

  public selectedSuggestionsState$ = select(
    this.state$,
    state => state.suggestionsByTypes.get(state.selectedSuggestionsType)!.state
  );

  public selectedSuggestionsLoadProgress$ = select(
    this.state$,
    state =>
      state.suggestionsByTypes.get(state.selectedSuggestionsType)!.loadProgress
  );

  public ownedPaths$ = select(this.state$, state => state.ownedPaths);

  constructor(readonly change: ChangeInfo) {
    super();
    // Side-effectful initialization of state$ is ok because this happens
    // during construction time.
    const current = this.subject$.getValue();
    for (const suggestionType of Object.values(SuggestionsType)) {
      current.suggestionsByTypes.set(suggestionType, {
        files: undefined,
        state: SuggestionsState.NotLoaded,
        loadProgress: undefined,
      });
    }
  }

  get state() {
    return this.subject$.getValue();
  }

  get selectedSuggestions() {
    const current = this.subject$.getValue();
    return current.suggestionsByTypes.get(current.selectedSuggestionsType);
  }

  getSuggestionsByType(suggestionsType: SuggestionsType) {
    const current = this.subject$.getValue();
    return Object.freeze(current.suggestionsByTypes.get(suggestionsType)!);
  }

  private setState(state: CodeOwnersState) {
    this.subject$.next(Object.freeze(state));
  }

  setBranchConfig(branchConfig: CodeOwnerBranchConfigInfo) {
    const current = this.subject$.getValue();
    if (current.branchConfig === branchConfig) return;
    this.setState({...current, branchConfig});
  }

  setStatus(status: Status) {
    const current = this.subject$.getValue();
    if (current.status === status) return;
    this.setState({...current, status});
  }

  setUserRole(userRole: UserRole) {
    const current = this.subject$.getValue();
    if (current.userRole === userRole) return;
    this.setState({...current, userRole});
  }

  setAreAllFilesApproved(areAllFilesApproved: boolean) {
    const current = this.subject$.getValue();
    if (current.areAllFilesApproved === areAllFilesApproved) return;
    this.setState({...current, areAllFilesApproved});
  }

  setShowSuggestions(showSuggestions: boolean) {
    const current = this.subject$.getValue();
    if (current.showSuggestions === showSuggestions) return;
    this.setState({...current, showSuggestions});
  }

  setSelectedSuggestionType(selectedSuggestionsType: SuggestionsType) {
    const current = this.subject$.getValue();
    if (current.selectedSuggestionsType === selectedSuggestionsType) return;
    this.setState({...current, selectedSuggestionsType});
  }

  _setPluginStatus(pluginStatus: PluginStatus) {
    const current = this.subject$.getValue();
    if (this._arePluginStatusesEqual(current.pluginStatus, pluginStatus))
      return;
    this.setState({...current, pluginStatus});
  }

  private updateSuggestion(
    suggestionsType: SuggestionsType,
    suggestionsUpdate: Partial<Suggestion>
  ) {
    const current = this.subject$.getValue();
    const nextState = {
      ...current,
      suggestionsByTypes: new Map(current.suggestionsByTypes),
    };
    nextState.suggestionsByTypes.set(suggestionsType, {
      ...nextState.suggestionsByTypes.get(suggestionsType)!,
      ...suggestionsUpdate,
    });
    this.setState(nextState);
  }

  setSuggestionsFiles(
    suggestionsType: SuggestionsType,
    files: Array<FetchedFile>
  ) {
    const current = this.subject$.getValue();
    const suggestions = current.suggestionsByTypes.get(suggestionsType);
    if (!suggestions) return;
    if (suggestions.files === files) return;
    if (deepEqual(suggestions.files, files)) return;
    this.updateSuggestion(suggestionsType, {files});
  }

  setSuggestionsState(
    suggestionsType: SuggestionsType,
    state: SuggestionsState
  ) {
    const current = this.subject$.getValue();
    const suggestions = current.suggestionsByTypes.get(suggestionsType);
    if (!suggestions) return;
    if (suggestions.state === state) return;
    this.updateSuggestion(suggestionsType, {state});
  }

  setSuggestionsLoadProgress(
    suggestionsType: SuggestionsType,
    loadProgress: string
  ) {
    const current = this.subject$.getValue();
    const suggestions = current.suggestionsByTypes.get(suggestionsType);
    if (!suggestions) return;
    if (suggestions.loadProgress === loadProgress) return;
    this.updateSuggestion(suggestionsType, {loadProgress});
  }

  setOwnedPaths(ownedPathsInfo: OwnedPathsInfo | undefined) {
    const current = this.subject$.getValue();
    const ownedPaths = {
      oldPaths: new Set<string>(),
      newPaths: new Set<string>(),
    };
    for (const changed_file of ownedPathsInfo?.owned_changed_files ?? []) {
      if (changed_file.old_path?.owned)
        ownedPaths.oldPaths.add(changed_file.old_path.path);
      if (changed_file.new_path?.owned)
        ownedPaths.newPaths.add(changed_file.new_path.path);
    }
    const nextState = {
      ...current,
      ownedPaths,
    };
    this.setState(nextState);
  }

  setPluginEnabled(enabled: boolean) {
    this._setPluginStatus({
      state: enabled ? PluginState.Enabled : PluginState.Disabled,
    });
  }

  setServerConfigurationError(failedMessage: string) {
    this._setPluginStatus({
      state: PluginState.ServerConfigurationError,
      failedMessage,
    });
  }

  setPluginFailed(failedMessage: string) {
    this._setPluginStatus({state: PluginState.Failed, failedMessage});
  }

  _arePluginStatusesEqual(
    status1: PluginStatus | undefined,
    status2: PluginStatus | undefined
  ) {
    if (status1 === undefined || status2 === undefined) {
      return status1 === status2;
    }
    if (status1.state !== status2.state) return false;
    return isPluginErrorState(status1.state)
      ? status1.failedMessage === status2.failedMessage
      : true;
  }

  static getModel(change: ChangeInfo) {
    if (!codeOwnersModel || codeOwnersModel.change !== change) {
      codeOwnersModel = new CodeOwnersModel(change);
    }
    return codeOwnersModel;
  }
}
