/**
 * LIMITATION:
 * For NPM setup, this feature flag singleton is shared between RUM and Logs product.
 * This means that an experimental flag set on the RUM product will be set on the Logs product.
 * So keep in mind that in certain configurations, your experimental feature flag may affect other products.
 *
 * FORMAT:
 * All feature flags should be snake_cased
 */
// We want to use a real enum (i.e. not a const enum) here, to be able to check whether an arbitrary
// string is an expected feature flag

import { objectHasValue } from './utils/objectUtils'

// eslint-disable-next-line no-restricted-syntax
export enum ExperimentalFeature {
  TRACK_INTAKE_REQUESTS = 'track_intake_requests',
  USE_TREE_WALKER_FOR_ACTION_NAME = 'use_tree_walker_for_action_name',
  FEATURE_OPERATION_VITAL = 'feature_operation_vital',
  SHORT_SESSION_INVESTIGATION = 'short_session_investigation',
  START_STOP_ACTION = 'start_stop_action',
  START_STOP_RESOURCE = 'start_stop_resource',
  USE_CHANGE_RECORDS = 'use_change_records',
  USE_INCREMENTAL_CHANGE_RECORDS = 'use_incremental_change_records',
  LCP_SUBPARTS = 'lcp_subparts',
  INP_SUBPARTS = 'inp_subparts',
  TOO_MANY_REQUESTS_INVESTIGATION = 'too_many_requests_investigation',
}

const enabledExperimentalFeatures: Set<ExperimentalFeature> = new Set()

export function initFeatureFlags(enableExperimentalFeatures: string[] | undefined) {
  if (Array.isArray(enableExperimentalFeatures)) {
    addExperimentalFeatures(
      enableExperimentalFeatures.filter((flag): flag is ExperimentalFeature =>
        objectHasValue(ExperimentalFeature, flag)
      )
    )
  }
}

export function addExperimentalFeatures(enabledFeatures: ExperimentalFeature[]): void {
  enabledFeatures.forEach((flag) => {
    enabledExperimentalFeatures.add(flag)
  })
}

export function isExperimentalFeatureEnabled(featureName: ExperimentalFeature): boolean {
  return enabledExperimentalFeatures.has(featureName)
}

export function resetExperimentalFeatures(): void {
  enabledExperimentalFeatures.clear()
}

export function getExperimentalFeatures(): Set<ExperimentalFeature> {
  return enabledExperimentalFeatures
}
