const mwExperiments = mw.experiments;
/*
* Bucketing wrapper for creating AB-tests.
*
* Given a test name, sampling rate, and session ID, provides a class that buckets a user into
* a predefined bucket ("unsampled", "control", or "treatment") and starts an AB-test.
*/
const bucket = {
	UNSAMPLED: 'unsampled', // Old treatment: not sampled and not instrumented.
	CONTROL: 'control', // Old treatment: sampled and instrumented.
	TREATMENT: 'treatment' // New treatment: sampled and instrumented.
};

/**
 * Buckets users based on params and exposes an `isSampled` and `getBucket` method.
 *
 * @ignore
 * @param {Object} config Configuration object for AB test.
 * @param {string} config.testName
 * @param {number} config.samplingRate Sampling rate for the AB-test.
 * @param {number} config.sessionId Session ID for user bucketing.
 * @constructor
 */
function AB( config ) {
	const testName = config.testName;
	const samplingRate = config.samplingRate;
	const sessionId = config.sessionId;
	const test = {
		name: testName,
		enabled: !!samplingRate,
		buckets: {
			unsampled: 1 - samplingRate,
			control: samplingRate / 2,
			treatment: samplingRate / 2
		}
	};

	/**
	 * Gets the users AB-test bucket.
	 *
	 * A boolean instead of an enum is usually a code smell. However, the nature of A/B testing
	 * is to compare an A group's performance to a B group's so a boolean seems natural, even
	 * in the long term, and preferable to showing bucketing encoding ("unsampled", "control",
	 * "treatment") to callers which is necessary if getBucket(). The downside is that now two
	 * functions exist where one would suffice.
	 *
	 * @private
	 * @return {string} AB-test bucket, `bucket.UNSAMPLED` by default, `bucket.CONTROL` or
	 *                  `bucket.TREATMENT` buckets otherwise.
	 */
	function getBucket() {
		return mwExperiments.getBucket( test, sessionId );
	}

	function isControl() {
		return getBucket() === bucket.CONTROL;
	}

	function isTreatment() {
		return getBucket() === bucket.TREATMENT;
	}

	/**
	 * Checks whether or not a user is in the AB-test,
	 *
	 * @private
	 * @return {boolean}
	 */
	function isSampled() {
		return getBucket() !== bucket.UNSAMPLED; // I.e., `isControl() || isTreatment()`
	}

	return {
		isControl: isControl,
		isTreatment: isTreatment,
		isSampled: isSampled
	};
}

module.exports = AB;
