/**
 * @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,
  combineLatest,
  from,
  Observable,
  of,
  Subject,
  Subscription,
  timer,
} from 'rxjs';
import {
  catchError,
  filter,
  switchMap,
  takeUntil,
  takeWhile,
  throttleTime,
  withLatestFrom,
} from 'rxjs/operators';
import {
  Action,
  ChangeData,
  CheckResult,
  CheckRun,
  ChecksApiConfig,
  ChecksProvider,
  FetchResponse,
  ResponseCode,
} from '../../api/checks';
import {change$, changeNum$, latestPatchNum$} from '../change/change-model';
import {
  ChecksPatchset,
  checksSelectedPatchsetNumber$,
  checkToPluginMap$,
  updateStateSetError,
  updateStateSetLoading,
  updateStateSetNotLoggedIn,
  updateStateSetPatchset,
  updateStateSetProvider,
  updateStateSetResults,
  updateStateUpdateResult,
} from './checks-model';
import {ChangeInfo, NumericChangeId, PatchSetNumber} from '../../types/common';
import {Finalizable} from '../registry';
import {getCurrentRevision} from '../../utils/change-util';
import {getShaByPatchNum} from '../../utils/patch-set-util';
import {assertIsDefined} from '../../utils/common-util';
import {ReportingService} from '../gr-reporting/gr-reporting';
import {routerPatchNum$} from '../router/router-model';
import {Execution} from '../../constants/reporting';
import {fireAlert, fireEvent} from '../../utils/event-util';

export class ChecksService implements Finalizable {
  private readonly providers: {[name: string]: ChecksProvider} = {};

  private readonly reloadSubjects: {[name: string]: Subject<void>} = {};

  private checkToPluginMap = new Map<string, string>();

  private changeNum?: NumericChangeId;

  private latestPatchNum?: PatchSetNumber;

  private readonly documentVisibilityChange$ = new BehaviorSubject(undefined);

  private readonly reloadListener: () => void;

  private readonly subscriptions: Subscription[] = [];

  private readonly visibilityChangeListener: () => void;

  constructor(readonly reporting: ReportingService) {
    this.subscriptions.push(changeNum$.subscribe(x => (this.changeNum = x)));
    this.subscriptions.push(
      checkToPluginMap$.subscribe(map => {
        this.checkToPluginMap = map;
      })
    );
    this.subscriptions.push(
      combineLatest([routerPatchNum$, latestPatchNum$]).subscribe(
        ([routerPs, latestPs]) => {
          this.latestPatchNum = latestPs;
          if (latestPs === undefined) {
            this.setPatchset(undefined);
          } else if (typeof routerPs === 'number') {
            this.setPatchset(routerPs);
          } else {
            this.setPatchset(latestPs);
          }
        }
      )
    );
    this.visibilityChangeListener = () => {
      this.documentVisibilityChange$.next(undefined);
    };
    document.addEventListener(
      'visibilitychange',
      this.visibilityChangeListener
    );
    this.reloadListener = () => this.reloadAll();
    document.addEventListener('reload', this.reloadListener);
  }

  finalize() {
    document.removeEventListener('reload', this.reloadListener);
    document.removeEventListener(
      'visibilitychange',
      this.visibilityChangeListener
    );
    for (const s of this.subscriptions) {
      s.unsubscribe();
    }
    this.subscriptions.splice(0, this.subscriptions.length);
  }

  setPatchset(num?: PatchSetNumber) {
    updateStateSetPatchset(num === this.latestPatchNum ? undefined : num);
  }

  reload(pluginName: string) {
    this.reloadSubjects[pluginName].next();
  }

  reloadAll() {
    Object.keys(this.providers).forEach(key => this.reload(key));
  }

  reloadForCheck(checkName?: string) {
    if (!checkName) return;
    const plugin = this.checkToPluginMap.get(checkName);
    if (plugin) this.reload(plugin);
  }

  updateResult(pluginName: string, run: CheckRun, result: CheckResult) {
    updateStateUpdateResult(pluginName, run, result, ChecksPatchset.LATEST);
    updateStateUpdateResult(pluginName, run, result, ChecksPatchset.SELECTED);
  }

  triggerAction(action?: Action, run?: CheckRun) {
    if (!action?.callback) return;
    if (!this.changeNum) return;
    const patchSet = run?.patchset ?? this.latestPatchNum;
    if (!patchSet) return;
    const promise = action.callback(
      this.changeNum,
      patchSet,
      run?.attempt,
      run?.externalId,
      run?.checkName,
      action.name
    );
    // If plugins return undefined or not a promise, then show no toast.
    if (!promise?.then) return;

    fireAlert(document, `Triggering action '${action.name}' ...`);
    from(promise)
      // If the action takes longer than 5 seconds, then most likely the
      // user is either not interested or the result not relevant anymore.
      .pipe(takeUntil(timer(5000)))
      .subscribe(result => {
        if (result.errorMessage || result.message) {
          fireAlert(document, `${result.message ?? result.errorMessage}`);
        } else {
          fireEvent(document, 'hide-alert');
        }
        if (result.shouldReload) {
          this.reloadForCheck(run?.checkName);
        }
      });
  }

  register(
    pluginName: string,
    provider: ChecksProvider,
    config: ChecksApiConfig
  ) {
    if (this.providers[pluginName]) {
      console.warn(
        `Plugin '${pluginName}' was trying to register twice as a Checks UI provider. Ignored.`
      );
      return;
    }
    this.providers[pluginName] = provider;
    this.reloadSubjects[pluginName] = new BehaviorSubject<void>(undefined);
    updateStateSetProvider(pluginName, ChecksPatchset.LATEST);
    updateStateSetProvider(pluginName, ChecksPatchset.SELECTED);
    this.initFetchingOfData(pluginName, config, ChecksPatchset.LATEST);
    this.initFetchingOfData(pluginName, config, ChecksPatchset.SELECTED);
  }

  initFetchingOfData(
    pluginName: string,
    config: ChecksApiConfig,
    patchset: ChecksPatchset
  ) {
    const pollIntervalMs = (config?.fetchPollingIntervalSeconds ?? 60) * 1000;
    // Various events should trigger fetching checks from the provider:
    // 1. Change number and patchset number changes.
    // 2. Specific reload requests.
    // 3. Regular polling starting with an initial fetch right now.
    // 4. A hidden Gerrit tab becoming visible.
    this.subscriptions.push(
      combineLatest([
        changeNum$,
        patchset === ChecksPatchset.LATEST
          ? latestPatchNum$
          : checksSelectedPatchsetNumber$,
        this.reloadSubjects[pluginName].pipe(throttleTime(1000)),
        timer(0, pollIntervalMs),
        this.documentVisibilityChange$,
      ])
        .pipe(
          takeWhile(_ => !!this.providers[pluginName]),
          filter(_ => document.visibilityState !== 'hidden'),
          withLatestFrom(change$),
          switchMap(
            ([[changeNum, patchNum], change]): Observable<FetchResponse> => {
              if (!change || !changeNum || !patchNum) return of(this.empty());
              if (typeof patchNum !== 'number') return of(this.empty());
              assertIsDefined(change.revisions, 'change.revisions');
              const patchsetSha = getShaByPatchNum(change.revisions, patchNum);
              // Sometimes patchNum is updated earlier than change, so change
              // revisions don't have patchNum yet
              if (!patchsetSha) return of(this.empty());
              const data: ChangeData = {
                changeNumber: changeNum,
                patchsetNumber: patchNum,
                patchsetSha,
                repo: change.project,
                commitMessage: getCurrentRevision(change)?.commit?.message,
                changeInfo: change as ChangeInfo,
              };
              return this.fetchResults(pluginName, data, patchset);
            }
          ),
          catchError(e => {
            // This should not happen and is really severe, because it means that
            // the Observable has terminated and we won't recover from that. No
            // further attempts to fetch results for this plugin will be made.
            this.reporting.error(e, `checks-service crash for ${pluginName}`);
            return of(this.createErrorResponse(pluginName, e));
          })
        )
        .subscribe(response => {
          switch (response.responseCode) {
            case ResponseCode.ERROR: {
              const message = response.errorMessage ?? '-';
              this.reporting.reportExecution(Execution.CHECKS_API_ERROR, {
                plugin: pluginName,
                message,
              });
              updateStateSetError(pluginName, message, patchset);
              break;
            }
            case ResponseCode.NOT_LOGGED_IN: {
              assertIsDefined(response.loginCallback, 'loginCallback');
              this.reporting.reportExecution(
                Execution.CHECKS_API_NOT_LOGGED_IN,
                {
                  plugin: pluginName,
                }
              );
              updateStateSetNotLoggedIn(
                pluginName,
                response.loginCallback,
                patchset
              );
              break;
            }
            case ResponseCode.OK: {
              updateStateSetResults(
                pluginName,
                response.runs ?? [],
                response.actions ?? [],
                response.links ?? [],
                patchset
              );
              break;
            }
          }
        })
    );
  }

  private empty(): FetchResponse {
    return {
      responseCode: ResponseCode.OK,
      runs: [],
    };
  }

  private createErrorResponse(
    pluginName: string,
    message: object
  ): FetchResponse {
    return {
      responseCode: ResponseCode.ERROR,
      errorMessage:
        `Error message from plugin '${pluginName}':` +
        ` ${JSON.stringify(message)}`,
    };
  }

  private fetchResults(
    pluginName: string,
    data: ChangeData,
    patchset: ChecksPatchset
  ): Observable<FetchResponse> {
    updateStateSetLoading(pluginName, patchset);
    const timer = this.reporting.getTimer('ChecksPluginFetch');
    const fetchPromise = this.providers[pluginName]
      .fetch(data)
      .then(response => {
        timer.end({pluginName});
        return response;
      });
    return from(fetchPromise).pipe(
      catchError(e => of(this.createErrorResponse(pluginName, e)))
    );
  }
}
