"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getActiveViews = exports.getViewStates = void 0;
const utils_1 = require("../utils");
const condition_1 = __importDefault(require("../lib/condition"));
const url_1 = __importDefault(require("../lib/matchers/url"));
const constants_1 = require("../constants");
const error_1 = require("./error");
const matchersMap = {
    url: url_1.default,
};
/**
 * Given a list of views and the current URL, return a viewState Object
 * in which the key is a view id and the value is the evaluation of the
 * view. If the evaluator cannot determine a value from a view, the
 * viewState does not include any information about that view. Note
 * that only the url match type is valid for view conditions here.
 *
 * @param {Object} webManifest
 * @param {Object} inputs
 * @return {Object}
 */
function getViewStates(webManifest, inputs, logger) {
    const url = inputs.url;
    const views = webManifest.views;
    const isDynamicWebSupportEnabled = webManifest.dynamicWebsiteSupport;
    if (!url) {
        throw new error_1.ViewError(`Invalid URL: URL is null`);
    }
    return views.reduce((viewStates, view) => {
        let result = false;
        const { activationType, staticConditions } = view;
        if (!isDynamicWebSupportEnabled) {
            if (!isActivationTypeImmediate(activationType)) {
                logger.logViewEvaluation(view.id, url, false, 'Trigger requires dynamic website support enabled');
                return viewStates;
            }
            if (hasUnsupportedConditions(staticConditions, url, view, logger)) {
                return viewStates;
            }
        }
        if (!shouldTriggerImmediately(activationType)) {
            logger.logViewEvaluation(view.id, url, false, 'Trigger not immediately evaluated at edge');
            return viewStates;
        }
        if (staticConditions.length === 0) {
            result = true;
        }
        else {
            result = condition_1.default.evaluate(staticConditions, function (condition) {
                var type = condition.type;
                var matcher = matchersMap[type];
                if (!matcher) {
                    return undefined;
                }
                return matcher.match({ url }, condition);
            });
        }
        if (result === undefined) {
            logger.logViewEvaluation(view.id, url, false, 'Conditions are not evaluated at edge');
            return viewStates;
        }
        else if (result) {
            logger.logViewEvaluation(view.id, url, true, null);
        }
        else {
            logger.logViewEvaluation(view.id, url, false, 'Conditions did not match');
        }
        viewStates[view.id] = result;
        return viewStates;
    }, {});
}
exports.getViewStates = getViewStates;
/**
 * Given a list of views and the current viewStates, return a list of view ids
 * whose types immediately trigger and conditions pass.
 * @param {Array} views
 * @param {Object} viewStates
 * @return {Array<Object>}
 */
function getActiveViews(views, viewStates) {
    return views
        .filter(view => viewStates[view.id])
        .map(v => (0, utils_1.nativePick)(v, ['id', 'apiName']));
}
exports.getActiveViews = getActiveViews;
/**
 * Used when support for dynamic website is not enabled, this traversal code
 * checks each leaf of the condition array. All conditions that are not
 * "url" are unsupportedConditions. It returns whether or not any unsupported
 * conditions were used.
 *
 * @param {Condition} staticConditions
 * @param {Object} view
 * @return {Boolean}
 */
function hasUnsupportedConditions(staticConditions, url, view, logger) {
    let result = false;
    try {
        result = condition_1.default.evaluate(staticConditions, function (condition) {
            var type = condition.type;
            var matcher = matchersMap[type];
            if (!matcher) {
                throw new error_1.ViewError(`Non-dynamic websites does not supported condition type "${condition.type}" for view id ${view.id}`);
            }
        });
    }
    catch (e) {
        logger.logViewEvaluation(view.id, url, false, e.toString());
        result = true;
    }
    // Condition.evalate() returns undefined if all condition types are "url".
    return !!result;
}
/**
 * Helper function to determine whether a given activationType should trigger
 * (ie, have its conditions evaluated) immediately.

 * Ported from https://github.com/optimizely/client-js/blob/21ce805e3dfb1ea3da9ed71ae3f9d39539d52a26/src/core/view/index.js#L346
 * @param {String|undefined} activationType
 * @returns {boolean}
 */
function shouldTriggerImmediately(activationType) {
    return (activationType === constants_1.ViewActivationTypes.immediate ||
        activationType === constants_1.ViewActivationTypes.URLChanged ||
        activationType === constants_1.ViewActivationTypes.DOMChanged ||
        // Legacy value for immediate types
        !activationType);
}
function isActivationTypeImmediate(activationType) {
    return activationType === constants_1.ViewActivationTypes.immediate || !activationType;
}
