import { lastValueFrom, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { DataFrameView } from '@grafana/data';
import { DataSourceWithBackend, getTemplateSrv, getBackendSrv, toDataQueryResponse } from '@grafana/runtime';
import { MACRO_NAMES } from './constants.js';
import { QueryFormat } from '../components/QueryEditor/types.js';

var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
class SqlDatasource extends DataSourceWithBackend {
  constructor(instanceSettings, templateSrv = getTemplateSrv()) {
    super(instanceSettings);
    this.templateSrv = templateSrv;
    __publicField(this, "id");
    __publicField(this, "name");
    __publicField(this, "interval");
    __publicField(this, "db");
    __publicField(this, "dataset");
    __publicField(this, "annotations", {});
    __publicField(this, "interpolateVariable", (value, variable) => {
      if (typeof value === "string") {
        if (variable.multi || variable.includeAll) {
          const result = this.getQueryModel().quoteLiteral(value);
          return result;
        } else {
          return value;
        }
      }
      if (typeof value === "number") {
        return value;
      }
      if (Array.isArray(value)) {
        const quotedValues = value.map((v) => this.getQueryModel().quoteLiteral(v));
        return quotedValues.join(",");
      }
      return value;
    });
    this.name = instanceSettings.name;
    this.id = instanceSettings.id;
    const settingsData = instanceSettings.jsonData || {};
    this.interval = settingsData.timeInterval || "1m";
    this.db = this.getDB();
  }
  interpolateVariablesInQueries(queries, scopedVars) {
    let expandedQueries = queries;
    if (queries && queries.length > 0) {
      expandedQueries = queries.map((query) => {
        const expandedQuery = {
          ...query,
          datasource: this.getRef(),
          rawSql: this.templateSrv.replace(query.rawSql, scopedVars, this.interpolateVariable),
          rawQuery: true
        };
        return expandedQuery;
      });
    }
    return expandedQueries;
  }
  filterQuery(query) {
    return !query.hide;
  }
  applyTemplateVariables(target, scopedVars) {
    const queryModel = this.getQueryModel(target, this.templateSrv, scopedVars);
    const rawSql = this.clean(queryModel.interpolate());
    return {
      refId: target.refId,
      datasource: this.getRef(),
      rawSql,
      format: target.format
    };
  }
  clean(value) {
    return value.replace(/''/g, "'");
  }
  async metricFindQuery(query, optionalOptions) {
    const rawSql = this.templateSrv.replace(
      query,
      getSearchFilterScopedVar({ query, wildcardChar: "%", options: optionalOptions }),
      this.interpolateVariable
    );
    const interpolatedQuery = {
      refId: "tempvar",
      datasource: this.getRef(),
      rawSql,
      format: QueryFormat.Table
    };
    const response = await this.runMetaQuery(interpolatedQuery, optionalOptions);
    return this.getResponseParser().transformMetricFindResponse(response);
  }
  async runSql(query, options) {
    const frame = await this.runMetaQuery({ rawSql: query, format: QueryFormat.Table, refId: options == null ? undefined : options.refId }, options);
    return new DataFrameView(frame);
  }
  runMetaQuery(request, options) {
    var _a, _b;
    const refId = request.refId || "meta";
    const queries = [{ ...request, datasource: request.datasource || this.getRef(), refId }];
    return lastValueFrom(
      getBackendSrv().fetch({
        url: "/api/ds/query",
        method: "POST",
        data: {
          from: (_a = options == null ? undefined : options.range) == null ? undefined : _a.from.valueOf().toString(),
          to: (_b = options == null ? undefined : options.range) == null ? undefined : _b.to.valueOf().toString(),
          queries
        },
        requestId: refId
      }).pipe(
        map((res) => {
          const rsp = toDataQueryResponse(res, queries);
          return rsp.data[0];
        })
      )
    );
  }
  testDatasource() {
    return lastValueFrom(
      getBackendSrv().fetch({
        url: "/api/ds/query",
        method: "POST",
        data: {
          from: "5m",
          to: "now",
          queries: [
            {
              refId: "A",
              intervalMs: 1,
              maxDataPoints: 1,
              datasource: this.getRef(),
              datasourceId: this.id,
              rawSql: "SELECT 1",
              format: "table"
            }
          ]
        }
      }).pipe(
        map(() => ({ status: "success", message: "Database Connection OK" })),
        catchError((err) => {
          return of(err);
        })
      )
    );
  }
  targetContainsTemplate(target) {
    let queryWithoutMacros = target.rawSql;
    MACRO_NAMES.forEach((value) => {
      queryWithoutMacros = (queryWithoutMacros == null ? undefined : queryWithoutMacros.replace(value, "")) || "";
    });
    return this.templateSrv.containsTemplate(queryWithoutMacros);
  }
}
const SEARCH_FILTER_VARIABLE = "__searchFilter";
const containsSearchFilter = (query) => query && typeof query === "string" ? query.indexOf(SEARCH_FILTER_VARIABLE) !== -1 : false;
const getSearchFilterScopedVar = (args) => {
  const { query, wildcardChar } = args;
  if (!containsSearchFilter(query)) {
    return {};
  }
  let { options } = args;
  options = options || { searchFilter: "" };
  const value = options.searchFilter ? `${options.searchFilter}${wildcardChar}` : `${wildcardChar}`;
  return {
    __searchFilter: {
      value,
      text: ""
    }
  };
};

export { SEARCH_FILTER_VARIABLE, SqlDatasource, containsSearchFilter, getSearchFilterScopedVar };
//# sourceMappingURL=SqlDatasource.js.map
