"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkABTestUrl = void 0;
const path_to_regexp_1 = require("path-to-regexp");
const murmurhash_1 = __importDefault(require("murmurhash"));
const console_1 = require("./console");
const _ = __importStar(require("../lib/lodash"));
const querystring = __importStar(require("querystring"));
const lodash_1 = require("lodash");
const SLUG_PARAM_KEY = "slug";
const INJECT_PARAM_REGEX = RegExp("\\[[A-Za-z0-9]*]", "g");
const parse = (querystring) => {
    return querystring
        .substring(querystring.indexOf("?") + 1)
        .split("&")
        .reduce((memo, param) => (Object.assign(Object.assign({}, memo), { [param.split("=")[0]]: param.split("=")[1] })), {});
};
exports.default = (path) => path_to_regexp_1.pathToRegexp(path)
    .toString()
    .replace(/\/(.*)\/\i/, "$1");
const isUriMatch = (originUrl, requestUrl) => {
    const result = new RegExp(`^${originUrl
        .replace(INJECT_PARAM_REGEX, "[0-9a-zA-Z-]*")
        .replace(/\//gi, "\\/")}$`).test(requestUrl);
    console_1.debug(`[isUriMatch]:${result} with originUrl: ${originUrl}, requestUrl: ${requestUrl}`);
    return result;
};
const isParamsMatch = (originUrlParams, querystring) => {
    const params = _.keys(parse(querystring));
    if (typeof originUrlParams === "string") {
        originUrlParams = [originUrlParams];
    }
    if (!_.isEmpty(originUrlParams) && _.isEmpty(params))
        return false;
    const result = _.isEqual(params.sort(), originUrlParams.sort());
    console_1.debug(`[isParamsMatch]:${result} with originUrlParams: ${JSON.stringify(originUrlParams)}, querystring: ${querystring}`);
    return result;
};
const rewriteUrlWithParams = (rewriteUrl, requestUrl, querystring) => {
    let result = rewriteUrl;
    _.forOwn(parse(querystring), function (value, key) {
        const valueReplaceSlash = _.replace(value, /\//g, "%2F");
        result = _.replace(result, `[${key}]`, `${valueReplaceSlash}`);
    });
    result = result.replace(`[${SLUG_PARAM_KEY}]`, _.last(requestUrl.split("/")) || "");
    return `${result}.html`;
};
const rewriteUrlWithExperimentGroups = (experimentGroups, request, originUrl) => {
    var _a, _b, _c;
    const queryParams = querystring.parse(request.querystring);
    console_1.debug(`[rewriteUrlWithExperimentGroups]: query params: ${JSON.stringify(queryParams)}`);
    const forceGroupIndex = queryParams.forceTestGroup;
    if (forceGroupIndex === "original") {
        console_1.debug(`[rewriteUrlWithExperimentGroups]: force use original url.`);
        return `${originUrl}.html`;
    }
    if (!lodash_1.isNil(forceGroupIndex) && experimentGroups[lodash_1.toNumber(forceGroupIndex)]) {
        console_1.debug(`[rewriteUrlWithExperimentGroups]: force serve url: ${experimentGroups[lodash_1.toNumber(forceGroupIndex)].url}`);
        return `${experimentGroups[lodash_1.toNumber(forceGroupIndex)].url}.html`;
    }
    const clientIp = request.clientIp;
    const hashMap = experimentGroups.reduce((acc, cur, index) => {
        acc = acc.concat(Array.from({ length: cur.ratio }, () => index));
        return acc;
    }, []);
    const hashIndex = murmurhash_1.default.v2(clientIp) % 100;
    const hitExperimentGroup = experimentGroups[hashMap[hashIndex]];
    let resultUrl = originUrl;
    if (hitExperimentGroup === null || hitExperimentGroup === void 0 ? void 0 : hitExperimentGroup.states) {
        const region = (_c = (_b = (_a = request.headers) === null || _a === void 0 ? void 0 : _a["cloudfront-viewer-country-region"]) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.value;
        if (!region) {
            resultUrl = originUrl;
        }
        else {
            console_1.debug(`[rewriteUrlWithExperimentGroups]: user region is ${region}`);
            resultUrl =
                hitExperimentGroup.states.findIndex((state) => state === region) >= 0
                    ? hitExperimentGroup.url
                    : originUrl;
        }
    }
    else if (hitExperimentGroup) {
        resultUrl = hitExperimentGroup.url;
    }
    console_1.debug(`[rewriteUrlWithExperimentGroups]: ${originUrl} -> ${resultUrl}}`);
    return `${resultUrl}.html`;
};
const checkABTestUrl = (manifest, request) => {
    console_1.debug(`[checkABTestUrl] before: ${JSON.stringify(manifest)}, ${JSON.stringify(request)}`);
    const abTests = manifest.abTests;
    if (!abTests || abTests.length === 0)
        return;
    const requestUri = request.uri.split(".")[0];
    for (const abTest of abTests) {
        console_1.debug(`[checkABTestUrl]: requestUri: ${requestUri}, check if in test: ${JSON.stringify(abTest)}`);
        const originUrl = abTest.originUrl;
        const experimentGroups = abTest.experimentGroups;
        if (isUriMatch(originUrl, requestUri)) {
            request.uri = rewriteUrlWithExperimentGroups(experimentGroups, request, originUrl);
            break;
        }
    }
    console_1.debug(`[checkABTestUrl] After: ${request.uri}`);
};
exports.checkABTestUrl = checkABTestUrl;
