import { isSystemOverrideWithRef, ByNamesMatcherMode, FieldType, getFieldDisplayName, FieldMatcherID, fieldMatchers } from '@grafana/data';
import { SeriesVisibilityChangeMode } from '@grafana/ui';

const displayOverrideRef = "hideSeriesFrom";
const isHideSeriesOverride = isSystemOverrideWithRef(displayOverrideRef);
function seriesVisibilityConfigFactory(label, mode, fieldConfig, data) {
  if (mode === "setExactly") {
    const overrides2 = fieldConfig.overrides.filter((o) => !isHideSeriesOverride(o));
    if (label == null || Array.isArray(label) && label.length === getDisplayNames(data).length) {
      return { ...fieldConfig, overrides: overrides2 };
    }
    const override2 = createOverride$1(Array.isArray(label) ? label : [label]);
    return { ...fieldConfig, overrides: [...overrides2, override2] };
  }
  const { overrides } = fieldConfig;
  const displayName = label;
  const currentIndex = overrides.findIndex(isHideSeriesOverride);
  if (currentIndex < 0) {
    if (mode === SeriesVisibilityChangeMode.ToggleSelection) {
      const override3 = createOverride$1([displayName, ...getNamesOfHiddenFields(overrides, data)]);
      return {
        ...fieldConfig,
        overrides: [...fieldConfig.overrides, override3]
      };
    }
    const displayNames = getDisplayNames(data, displayName);
    const override2 = createOverride$1(displayNames);
    return {
      ...fieldConfig,
      overrides: [...fieldConfig.overrides, override2]
    };
  }
  const overridesCopy = Array.from(overrides);
  const [current] = overridesCopy.splice(currentIndex, 1);
  if (mode === SeriesVisibilityChangeMode.ToggleSelection) {
    let existing = getExistingDisplayNames(current);
    const nameOfHiddenFields = getNamesOfHiddenFields(overridesCopy, data);
    if (nameOfHiddenFields.length > 0) {
      existing = existing.filter((el) => nameOfHiddenFields.indexOf(el) < 0);
    }
    if (existing[0] === displayName && existing.length === 1) {
      return {
        ...fieldConfig,
        overrides: overridesCopy
      };
    }
    const override2 = createOverride$1([displayName, ...nameOfHiddenFields]);
    return {
      ...fieldConfig,
      overrides: [...overridesCopy, override2]
    };
  }
  const override = createExtendedOverride(current, displayName);
  if (allFieldsAreExcluded(override, data)) {
    return {
      ...fieldConfig,
      overrides: overridesCopy
    };
  }
  return {
    ...fieldConfig,
    overrides: [...overridesCopy, override]
  };
}
function createOverride$1(names, mode = ByNamesMatcherMode.exclude, property) {
  property = property != null ? property : {
    id: "custom.hideFrom",
    value: {
      viz: true,
      legend: false,
      tooltip: true
    }
  };
  return {
    __systemRef: displayOverrideRef,
    matcher: {
      id: FieldMatcherID.byNames,
      options: {
        mode,
        names,
        prefix: mode === ByNamesMatcherMode.exclude ? "All except:" : void 0,
        readOnly: true
      }
    },
    properties: [
      {
        ...property,
        value: {
          viz: true,
          legend: false,
          tooltip: true
        }
      }
    ]
  };
}
const createExtendedOverride = (current, displayName, mode = ByNamesMatcherMode.exclude) => {
  const property = current.properties.find((p) => p.id === "custom.hideFrom");
  const existing = getExistingDisplayNames(current);
  const index = existing.findIndex((name) => name === displayName);
  if (index < 0) {
    existing.push(displayName);
  } else {
    existing.splice(index, 1);
  }
  return createOverride$1(existing, mode, property);
};
const getExistingDisplayNames = (rule) => {
  var _a;
  const names = (_a = rule.matcher.options) == null ? void 0 : _a.names;
  if (!Array.isArray(names)) {
    return [];
  }
  return [...names];
};
const allFieldsAreExcluded = (override, data) => {
  return getExistingDisplayNames(override).length === getDisplayNames(data).length;
};
const getDisplayNames = (data, excludeName) => {
  const unique = /* @__PURE__ */ new Set();
  for (const frame of data) {
    for (const field of frame.fields) {
      if (field.type !== FieldType.number) {
        continue;
      }
      const name = getFieldDisplayName(field, frame, data);
      if (name === excludeName) {
        continue;
      }
      unique.add(name);
    }
  }
  return Array.from(unique);
};
const getNamesOfHiddenFields = (overrides, data) => {
  var _a;
  let names = [];
  for (const override of overrides) {
    const property = override.properties.find((p) => p.id === "custom.hideFrom");
    if (property !== void 0 && ((_a = property.value) == null ? void 0 : _a.legend) === true) {
      const info = fieldMatchers.get(override.matcher.id);
      const matcher = info.get(override.matcher.options);
      for (const frame of data) {
        for (const field of frame.fields) {
          if (field.type !== FieldType.number) {
            continue;
          }
          const name = getFieldDisplayName(field, frame, data);
          if (matcher(field, frame, data)) {
            names.push(name);
          }
        }
      }
    }
  }
  return names;
};

export { seriesVisibilityConfigFactory };
//# sourceMappingURL=seriesVisibilityConfigFactory.js.map
