/**
 * Copyright 2017-2022, 2024-2026, Optimizely
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { LoggerFacade } from '../../logging/logger';
import { DecisionSource } from '../../utils/enums';
import { ProjectConfig } from '../../project_config/project_config';
import { DecisionResponse, Experiment, FeatureFlag, Holdout, OptimizelyDecideOption, OptimizelyUserContext, UserProfileService, UserProfileServiceAsync, Variation } from '../../shared_types';
import { CmabService } from './cmab/cmab_service';
import { OpType } from '../../utils/type';
import { Value } from '../../utils/promise/operation_value';
import { Platform } from '../../platform_support';
export declare const EXPERIMENT_NOT_RUNNING = "Experiment %s is not running.";
export declare const RETURNING_STORED_VARIATION = "Returning previously activated variation \"%s\" of experiment \"%s\" for user \"%s\" from user profile.";
export declare const USER_NOT_IN_EXPERIMENT = "User %s does not meet conditions to be in experiment %s.";
export declare const USER_HAS_NO_VARIATION = "User %s is in no variation of experiment %s.";
export declare const USER_HAS_VARIATION = "User %s is in variation %s of experiment %s.";
export declare const USER_FORCED_IN_VARIATION = "User %s is forced in variation %s.";
export declare const FORCED_BUCKETING_FAILED = "Variation key %s is not in datafile. Not activating user %s.";
export declare const EVALUATING_AUDIENCES_COMBINED = "Evaluating audiences for %s \"%s\": %s.";
export declare const AUDIENCE_EVALUATION_RESULT_COMBINED = "Audiences for %s %s collectively evaluated to %s.";
export declare const USER_IN_ROLLOUT = "User %s is in rollout of feature %s.";
export declare const USER_NOT_IN_ROLLOUT = "User %s is not in rollout of feature %s.";
export declare const FEATURE_HAS_NO_EXPERIMENTS = "Feature %s is not attached to any experiments.";
export declare const USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE = "User %s does not meet conditions for targeting rule %s.";
export declare const USER_NOT_BUCKETED_INTO_TARGETING_RULE = "User %s not bucketed into targeting rule %s due to traffic allocation. Trying everyone rule.";
export declare const USER_BUCKETED_INTO_TARGETING_RULE = "User %s bucketed into targeting rule %s.";
export declare const NO_ROLLOUT_EXISTS = "There is no rollout of feature %s.";
export declare const INVALID_ROLLOUT_ID = "Invalid rollout ID %s attached to feature %s";
export declare const ROLLOUT_HAS_NO_EXPERIMENTS = "Rollout of feature %s has no experiments";
export declare const IMPROPERLY_FORMATTED_EXPERIMENT = "Experiment key %s is improperly formatted.";
export declare const USER_HAS_FORCED_VARIATION = "Variation %s is mapped to experiment %s and user %s in the forced variation map.";
export declare const USER_MEETS_CONDITIONS_FOR_TARGETING_RULE = "User %s meets conditions for targeting rule %s.";
export declare const USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED = "Variation (%s) is mapped to flag (%s), rule (%s) and user (%s) in the forced decision map.";
export declare const USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED = "Variation (%s) is mapped to flag (%s) and user (%s) in the forced decision map.";
export declare const USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID = "Invalid variation is mapped to flag (%s), rule (%s) and user (%s) in the forced decision map.";
export declare const USER_HAS_FORCED_DECISION_WITH_NO_RULE_SPECIFIED_BUT_INVALID = "Invalid variation is mapped to flag (%s) and user (%s) in the forced decision map.";
export declare const CMAB_NOT_SUPPORTED_IN_SYNC = "CMAB is not supported in sync mode.";
export declare const CMAB_FETCH_FAILED = "Failed to fetch CMAB data for experiment %s.";
export declare const CMAB_FETCHED_VARIATION_INVALID = "Fetched variation %s for cmab experiment %s is invalid.";
export declare const HOLDOUT_NOT_RUNNING = "Holdout %s is not running.";
export declare const USER_MEETS_CONDITIONS_FOR_HOLDOUT = "User %s meets conditions for holdout %s.";
export declare const USER_DOESNT_MEET_CONDITIONS_FOR_HOLDOUT = "User %s does not meet conditions for holdout %s.";
export declare const USER_BUCKETED_INTO_HOLDOUT_VARIATION = "User %s is in variation %s of holdout %s.";
export declare const USER_NOT_BUCKETED_INTO_HOLDOUT_VARIATION = "User %s is in no holdout variation.";
export interface DecisionObj {
    experiment: Experiment | Holdout | null;
    variation: Variation | null;
    decisionSource: DecisionSource;
    cmabUuid?: string;
}
interface DecisionServiceOptions {
    userProfileService?: UserProfileService;
    userProfileServiceAsync?: UserProfileServiceAsync;
    logger?: LoggerFacade;
    UNSTABLE_conditionEvaluators: unknown;
    cmabService: CmabService;
}
export type DecisionReason = [string, ...any[]];
export type VariationIdWithCmabParams = {
    variationId?: string;
    cmabUuid?: string;
};
export type VariationKeyWithCmabParams = {
    variationKey?: string;
    cmabUuid?: string;
};
export type DecisionResult = DecisionResponse<DecisionObj>;
type LocalHoldoutResult = DecisionResponse<DecisionObj> & {
    holdoutDecision: true;
};
type ExperimentEvaluationResult = DecisionResponse<VariationKeyWithCmabParams> & {
    holdoutDecision?: false;
};
export type ExperimentRuleResponse = ExperimentEvaluationResult | LocalHoldoutResult;
export type DecideOptionsMap = Partial<Record<OptimizelyDecideOption, boolean>>;
export declare const CMAB_DUMMY_ENTITY_ID = "$";
export declare const LOGGER_NAME = "DecisionService";
/**
 * Optimizely's decision service that determines which variation of an experiment the user will be allocated to.
 *
 * The decision service contains all logic around how a user decision is made. This includes all of the following (in order):
 *   1. Checking experiment status
 *   2. Checking forced bucketing
 *   3. Checking whitelisting
 *   4. Checking user profile service for past bucketing decisions (sticky bucketing)
 *   5. Checking audience targeting
 *   6. Using Murmurhash3 to bucket the user.
 *
 * @constructor
 * @param   {DecisionServiceOptions}      options
 * @returns {DecisionService}
 */
export declare class DecisionService {
    private logger?;
    private audienceEvaluator;
    private forcedVariationMap;
    private userProfileService?;
    private userProfileServiceAsync?;
    private cmabService;
    constructor(options: DecisionServiceOptions);
    private isCmab;
    /**
     * Resolves the variation into which the visitor will be bucketed.
     *
     * @param {ProjectConfig} configObj - The parsed project configuration object.
     * @param {Experiment} experiment - The experiment for which the variation is being resolved.
     * @param {OptimizelyUserContext} user - The user context associated with this decision.
     * @returns {DecisionResponse<string|null>} - A DecisionResponse containing the variation the user is bucketed into,
     *                                            along with the decision reasons.
     */
    private resolveVariation;
    private getDecisionForCmabExperiment;
    private getDecisionFromBucketer;
    /**
     * Gets variation where visitor will be bucketed.
     * @param  {ProjectConfig}                          configObj         The parsed project configuration object
     * @param  {Experiment}                             experiment
     * @param  {OptimizelyUserContext}                  user              A user context
     * @param  {[key: string]: boolean}                 options           Optional map of decide options
     * @return {DecisionResponse<string|null>}          DecisionResponse containing the variation the user is bucketed into
     *                                                                    and the decide reasons.
     */
    getVariation(configObj: ProjectConfig, experiment: Experiment, user: OptimizelyUserContext, options?: DecideOptionsMap): DecisionResponse<string | null>;
    /**
     * Merges attributes from attributes[STICKY_BUCKETING_KEY] and userProfileService
     * @param  {string}               userId
     * @param  {UserAttributes}       attributes
     * @return {ExperimentBucketMap}  finalized copy of experiment_bucket_map
     */
    private resolveExperimentBucketMap;
    /**
     * Checks if user is whitelisted into any variation and return that variation if so
     * @param  {Experiment}                                 experiment
     * @param  {string}                                     userId
     * @return {DecisionResponse<Variation|null>}           DecisionResponse containing the forced variation if it exists
     *                                                      or user ID and the decide reasons.
     */
    private getWhitelistedVariation;
    /**
     * Checks whether the user is included in experiment audience
     * @param  {ProjectConfig}                configObj            The parsed project configuration object
     * @param  {string}                       experimentKey        Key of experiment being validated
     * @param  {string}                       evaluationAttribute  String representing experiment key or rule
     * @param  {string}                       userId               ID of user
     * @param  {UserAttributes}               attributes           Optional parameter for user's attributes
     * @param  {string}                       loggingKey           String representing experiment key or rollout rule. To be used in log messages only.
     * @return {DecisionResponse<boolean>}    DecisionResponse     DecisionResponse containing result true if user meets audience conditions and
     *                                                             the decide reasons.
     */
    private checkIfUserIsInAudience;
    /**
     * Given an experiment key and user ID, returns params used in bucketer call
     * @param  {ProjectConfig}         configObj     The parsed project configuration object
     * @param  {string}                experimentKey Experiment key used for bucketer
     * @param  {string}                bucketingId   ID to bucket user into
     * @param  {string}                userId        ID of user to be bucketed
     * @return {BucketerParams}
     */
    private buildBucketerParams;
    /**
     * Determines if a user should be bucketed into a holdout variation.
     * @param {ProjectConfig} configObj - The parsed project configuration object.
     * @param {Holdout} holdout - The holdout to evaluate.
     * @param {OptimizelyUserContext} user - The user context.
     * @returns {DecisionResponse<DecisionObj>} - DecisionResponse containing holdout decision and reasons.
     */
    private getVariationForHoldout;
    /**
     * Pull the stored variation out of the experimentBucketMap for an experiment/userId
     * @param  {ProjectConfig}        configObj            The parsed project configuration object
     * @param  {Experiment}           experiment
     * @param  {string}               userId
     * @param  {ExperimentBucketMap}  experimentBucketMap  mapping experiment => { variation_id: <variationId> }
     * @return {Variation|null}       the stored variation or null if the user profile does not have one for the given experiment
     */
    private getStoredVariation;
    /**
     * Get the user profile with the given user ID
     * @param  {string} userId
     * @return {UserProfile} the stored user profile or an empty profile if one isn't found or error
     */
    private getUserProfile;
    private updateUserProfile;
    /**
     * Saves the bucketing decision to the user profile
     * @param {Experiment}          experiment
     * @param {Variation}           variation
     * @param {string}              userId
     * @param {ExperimentBucketMap} experimentBucketMap
     */
    private saveUserProfile;
    /**
     * Determines variations for the specified feature flags.
     *
     * @param {ProjectConfig} configObj - The parsed project configuration object.
     * @param {FeatureFlag[]} featureFlags - The feature flags for which variations are to be determined.
     * @param {OptimizelyUserContext} user - The user context associated with this decision.
     * @param {Record<string, boolean>} options - An optional map of decision options.
     * @returns {DecisionResponse<DecisionObj>[]} - An array of DecisionResponse containing objects with
     *                                               experiment, variation, decisionSource properties, and decision reasons.
     */
    getVariationsForFeatureList(configObj: ProjectConfig, featureFlags: FeatureFlag[], user: OptimizelyUserContext, options?: DecideOptionsMap): DecisionResult[];
    resolveVariationsForFeatureList<OP extends OpType>(op: OP, configObj: ProjectConfig, featureFlags: FeatureFlag[], user: OptimizelyUserContext, options: DecideOptionsMap): Value<OP, DecisionResult[]>;
    private resolveVariationForFlag;
    /**
     * Given a feature, user ID, and attributes, returns a decision response containing
     * an object representing a decision and decide reasons. If the user was bucketed into
     * a variation for the given feature and attributes, the decision object will have variation and
     * experiment properties (both objects), as well as a decisionSource property.
     * decisionSource indicates whether the decision was due to a rollout or an
     * experiment.
     * @param   {ProjectConfig}               configObj         The parsed project configuration object
     * @param   {FeatureFlag}                 feature           A feature flag object from project configuration
     * @param   {OptimizelyUserContext}       user              A user context
     * @param   {[key: string]: boolean}      options           Map of decide options
     * @return  {DecisionResponse}            DecisionResponse  DecisionResponse containing an object with experiment, variation, and decisionSource
     *                                                          properties and decide reasons. If the user was not bucketed into a variation, the variation
     *                                                          property in decision object is null.
     */
    getVariationForFeature(configObj: ProjectConfig, feature: FeatureFlag, user: OptimizelyUserContext, options?: DecideOptionsMap): DecisionResponse<DecisionObj>;
    private getVariationForFeatureExperiment;
    private traverseFeatureExperimentList;
    private getVariationForRollout;
    /**
     * Get bucketing Id from user attributes.
     * @param   {string}          userId
     * @param   {UserAttributes}  attributes
     * @returns {string}          Bucketing Id if it is a string type in attributes, user Id otherwise.
     */
    private getBucketingId;
    /**
     * Finds a validated forced decision for specific flagKey and optional ruleKey.
     * @param     {ProjectConfig}         config               A projectConfig.
     * @param     {OptimizelyUserContext} user                 A Optimizely User Context.
     * @param     {string}                flagKey              A flagKey.
     * @param     {ruleKey}               ruleKey              A ruleKey (optional).
     * @return    {DecisionResponse<Variation|null>}  DecisionResponse object containing valid variation object and decide reasons.
     */
    findValidatedForcedDecision(config: ProjectConfig, user: OptimizelyUserContext, flagKey: string, ruleKey?: string): DecisionResponse<Variation | null>;
    /**
     * Removes forced variation for given userId and experimentKey
     * @param  {string} userId         String representing the user id
     * @param  {string} experimentId   Number representing the experiment id
     * @param  {string} experimentKey  Key representing the experiment id
     * @throws If the user id is not valid or not in the forced variation map
     */
    private removeForcedVariation;
    /**
     * Sets forced variation for given userId and experimentKey
     * @param  {string} userId        String representing the user id
     * @param  {string} experimentId  Number representing the experiment id
     * @param  {number} variationId   Number representing the variation id
     * @throws If the user id is not valid
     */
    private setInForcedVariationMap;
    /**
     * Gets the forced variation key for the given user and experiment.
     * @param  {ProjectConfig}                  configObj         Object representing project configuration
     * @param  {string}                         experimentKey     Key for experiment.
     * @param  {string}                         userId            The user Id.
     * @return {DecisionResponse<string|null>}                    DecisionResponse containing variation which the given user and experiment
     *                                                            should be forced into and the decide reasons.
     */
    getForcedVariation(configObj: ProjectConfig, experimentKey: string, userId: string): DecisionResponse<string | null>;
    /**
     * Sets the forced variation for a user in a given experiment
     * @param  {ProjectConfig}  configObj      Object representing project configuration
     * @param  {string}         experimentKey  Key for experiment.
     * @param  {string}         userId         The user Id.
     * @param  {string|null}    variationKey   Key for variation. If null, then clear the existing experiment-to-variation mapping
     * @return {boolean}     A boolean value that indicates if the set completed successfully.
     */
    setForcedVariation(configObj: ProjectConfig, experimentKey: string, userId: string, variationKey: string | null): boolean;
    private getVariationFromExperimentRule;
    private getVariationFromDeliveryRule;
}
/**
 * Creates an instance of the DecisionService.
 * @param  {DecisionServiceOptions}     options       Configuration options
 * @return {Object}                     An instance of the DecisionService
 */
export declare function createDecisionService(options: DecisionServiceOptions): DecisionService;
export declare const __platforms: Platform[];
export {};
