import { type Observable, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

import { type AnnotationEvent, type DataSourceApi } from '@grafana/data';

import { executeAnnotationQuery } from '../../../annotations/executeAnnotationQuery';
import { type PanelModel } from '../../../dashboard/state/PanelModel';

import { type AnnotationQueryRunner, type AnnotationQueryRunnerOptions } from './types';
import { handleAnnotationQueryRunnerError } from './utils';

export class AnnotationsQueryRunner implements AnnotationQueryRunner {
  canRun(datasource?: DataSourceApi): boolean {
    if (!datasource) {
      return false;
    }

    return Boolean(!datasource.annotationQuery || datasource.annotations);
  }

  run({ annotation, datasource, dashboard, range }: AnnotationQueryRunnerOptions): Observable<AnnotationEvent[]> {
    if (!this.canRun(datasource)) {
      return of([]);
    }

    const panel: PanelModel = {} as PanelModel; // deliberate setting panel to empty object because executeAnnotationQuery shouldn't depend on panelModel

    return executeAnnotationQuery({ dashboard, range, panel }, datasource!, annotation).pipe(
      map((result) => {
        return result.events ?? [];
      }),
      catchError(handleAnnotationQueryRunnerError)
    );
  }
}
