import { isString } from 'lodash';
import { of } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators';
import { FieldType, getFieldDisplayName, AnnotationEventFieldSource, standardTransformers } from '@grafana/data';
import { config } from '@grafana/runtime';

const standardAnnotationSupport = {
  /**
   * Assume the stored value is standard model.
   */
  prepareAnnotation: (json) => {
    if (isString(json == null ? void 0 : json.query)) {
      const { query, ...rest } = json;
      return {
        ...rest,
        target: {
          refId: "annotation_query",
          query
        },
        mappings: {}
      };
    }
    return json;
  },
  /**
   * Default will just return target from the annotation.
   */
  prepareQuery: (anno) => anno.target,
  /**
   * Provides default processing from dataFrame to annotation events.
   */
  processEvents: (anno, data) => {
    return getAnnotationsFromData(data, anno.mappings);
  }
};
function singleFrameFromPanelData() {
  return (source) => source.pipe(
    mergeMap((data) => {
      if (!(data == null ? void 0 : data.length)) {
        return of(void 0);
      }
      if (data.length === 1) {
        return of(data[0]);
      }
      const ctx = {
        interpolate: (v) => v
      };
      return of(data).pipe(
        standardTransformers.mergeTransformer.operator({}, ctx),
        map((d) => d[0])
      );
    })
  );
}
const annotationEventNames = [
  {
    key: "time",
    field: (frame) => frame.fields.find((f) => f.type === FieldType.time),
    placeholder: "time, or the first time field"
  },
  { key: "timeEnd", help: "When this field is defined, the annotation will be treated as a range" },
  {
    key: "title"
  },
  {
    key: "text",
    field: (frame) => frame.fields.find((f) => f.type === FieldType.string),
    placeholder: "text, or the first text field"
  },
  { key: "tags", split: ",", help: "The results will be split on comma (,)" },
  {
    key: "id"
  }
];
const publicDashboardEventNames = [
  {
    key: "color"
  },
  {
    key: "isRegion"
  },
  {
    key: "source"
  }
];
const alertEventAndAnnotationFields = [
  ...config.publicDashboardAccessToken ? publicDashboardEventNames : [],
  ...annotationEventNames,
  { key: "userId" },
  { key: "login" },
  { key: "email" },
  { key: "prevState" },
  { key: "newState" },
  { key: "data" },
  { key: "panelId" },
  { key: "alertId" },
  { key: "dashboardId" },
  { key: "dashboardUID" }
];
function getAnnotationsFromData(data, options) {
  return of(data).pipe(
    singleFrameFromPanelData(),
    map((frame) => {
      if (!(frame == null ? void 0 : frame.length)) {
        return [];
      }
      let hasTime = false;
      let hasText = false;
      const byName = {};
      for (const f of frame.fields) {
        const name = getFieldDisplayName(f, frame);
        byName[name.toLowerCase()] = f;
      }
      if (!options) {
        options = {};
      }
      const fields = [];
      for (const evts of alertEventAndAnnotationFields) {
        const opt = options[evts.key] || {};
        if (opt.source === AnnotationEventFieldSource.Skip) {
          continue;
        }
        const setter = { key: evts.key, split: evts.split };
        if (opt.source === AnnotationEventFieldSource.Text) {
          setter.text = opt.value;
        } else {
          const lower = (opt.value || evts.key).toLowerCase();
          setter.field = byName[lower];
          if (!setter.field && evts.field) {
            setter.field = evts.field(frame);
          }
        }
        if (setter.field || setter.text) {
          fields.push(setter);
          if (setter.key === "time") {
            hasTime = true;
          } else if (setter.key === "text") {
            hasText = true;
          }
        }
      }
      if (!hasTime || !hasText) {
        console.error("Cannot process annotation fields. No time or text present.");
        return [];
      }
      const events = [];
      for (let i = 0; i < frame.length; i++) {
        const anno = {
          type: "default",
          color: "red"
        };
        for (const f of fields) {
          let v = void 0;
          if (f.text) {
            v = f.text;
          } else if (f.field) {
            v = f.field.values[i];
            if (v !== void 0 && f.regex) {
              const match = f.regex.exec(v);
              if (match) {
                v = match[1] ? match[1] : match[0];
              }
            }
          }
          if (v !== null && v !== void 0) {
            if (f.split && typeof v === "string") {
              v = v.split(",");
            }
            anno[f.key] = v;
          }
        }
        events.push(anno);
      }
      return events;
    })
  );
}
const legacyRunner = [
  "prometheus",
  "loki",
  "elasticsearch",
  "grafana-opensearch-datasource"
  // external
];
function shouldUseLegacyRunner(datasource) {
  const { type } = datasource;
  return !datasource.annotations || legacyRunner.includes(type);
}

export { annotationEventNames, getAnnotationsFromData, publicDashboardEventNames, shouldUseLegacyRunner, singleFrameFromPanelData, standardAnnotationSupport };
//# sourceMappingURL=standardAnnotationsSupport.js.map
