"use strict";
/**
 * Facade for browser information provided by [ua-parser-js](https://www.npmjs.com/package/ua-parser-js).
 * Ported from https://github.com/optimizely/client-js/blob/92589a0adef089556ab986ee79345342be339116/src/core/lib/detect.js
 * @module
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseUA = void 0;
var UAParser = require('ua-parser-js');
/**
 * @typedef {Object} DetectionResults
 * A subset of the data returned by `ua-parser-js`, with some normalizations applied.
 *
 * @property {Object} browser
 * @property {string} browser.id
 *        A short code naming the browser.
 *        One of `['gc', 'ie', 'ff', 'edge', 'opera', 'safari', 'uc browser', 'samsung', 'facebook', 'unknown']`.
 * @property {string=} browser.version
 * @property {Object} platform
 * @property {string} platform.name
 *        OS name. Result from ua-parser-js, lowercased. (default: 'unknown')
 *        See https://github.com/faisalman/ua-parser-js/#methods for full list.
 * @property {string=} platform.version
 * @property {Object} device
 * @property {string} device.model,
 *        One of `['iphone', 'ipad', 'unknown']`.
 * @property {string} device.type
 *        One of `['console', 'desktop_laptop', 'mobile', 'tablet', 'smarttv', 'wearable', 'embedded', 'unknown']`.
 *        1. If a [type](https://github.com/faisalman/ua-parser-js/tree/0.7.12#methods) was parsed by ua-parser-js, use that.
 *        2. Else if `isMobile` is true, assume 'mobile' (many generic Androids are phones).
 *        3. Else if `browser.id === 'unknown'`, 'unknown' (probably a bot).
 *        4. Else, assume 'desktop_laptop'.
 * @property {boolean} device.isMobile
 *        True iff the device is a phone, tablet, or running an OS that is one of
 *        `['android', 'blackberry', 'ios', 'windows phone']`.
 */
/**
 * Parse the userAgent string and return a subset of the data.
 *
 * @param {string} userAgent User agent string
 * @returns {module:lib/detect~DetectionResults}
 */
function parseUA(userAgent) {
    // TODO (Lauren): Memoize this (https://optimizely.atlassian.net/browse/CJS-3092)
    var ua = new UAParser(userAgent);
    var browser = ua.getBrowser();
    var engine = ua.getEngine();
    var os = ua.getOS();
    var device = ua.getDevice();
    var normalizedPlatformName = (os.name || 'unknown').toLowerCase();
    var normalizedBrowserName = (browser.name || 'unknown').toLowerCase();
    var normalizedEngineName = (engine.name || 'unknown').toLowerCase();
    var isMobileDevice = isMobile(device.type, normalizedBrowserName, normalizedPlatformName);
    return {
        browser: {
            id: normalizeBrowserName(browser.name),
            version: browser.version || 'unknown',
        },
        engine: {
            name: normalizedEngineName,
            version: engine.version,
        },
        platform: {
            name: normalizedPlatformName,
            version: os.version,
        },
        device: {
            model: deviceModelNormalizationMap[device.model] || 'unknown',
            type: normalizeDeviceType(normalizedBrowserName, device.type, isMobileDevice),
            isMobile: isMobileDevice,
        },
    };
}
exports.parseUA = parseUA;
/**
 * @param {string|undefined} name
 * @returns {string}
 *        Normalized browser name (called a browser "code").
 * @private
 */
function normalizeBrowserName(name) {
    name = (name || '').toLowerCase();
    if (name in browserMap)
        return name;
    for (const code in browserMap) {
        if (browserMap.hasOwnProperty(code)) {
            if ((browserMap[code] || []).includes(name))
                return code;
        }
    }
    return 'unknown';
}
/**
 * Empirically, this works pretty well. Any changes to this should be
 * evaluated with https://github.com/optimizely/test-detect.
 *
 * @param {string} browserName
 * @param {string=} deviceType
 * @param {boolean} isMobile
 *        As computed by the function `isMobile`.
 * @returns {string}
 * @private
 */
function normalizeDeviceType(browserName, deviceType, isMobile) {
    if (deviceType) {
        return deviceType;
    }
    if (browserName === 'unknown') {
        // Unknown browser is probably a bot/crawler
        return 'unknown';
    }
    if (isMobile) {
        // Mostly generic Androids
        return 'mobile';
    }
    return 'desktop_laptop';
}
/**
 * It's a little complicated to detect if a device is mobile; we need to bring together
 * data from device and platform to get pretty good coverage.
 *
 * @private
 * @param {string=} deviceType
 * @param {string} normalizedBrowserName
 * @param {string} normalizedPlatform
 * @returns {boolean}
 */
var isMobile = function (deviceType, normalizedBrowserName, normalizedPlatform) {
    // Consider both 'mobile' (phone) and 'tablet' to be mobile devices.
    if (['mobile', 'tablet'].includes(deviceType)) {
        return true;
    }
    // Browsers which are only on mobile OSes
    if (['opera mini'].includes(normalizedBrowserName)) {
        return true;
    }
    // Platforms which are only on mobile devices (for now)
    var mobilePlatforms = ['android', 'blackberry', 'ios', 'windows phone'];
    if (mobilePlatforms.includes(normalizedPlatform)) {
        return true;
    }
    return false;
};
/**
 * Map browser code to long names (for compatibility with legacy browser conditions).
 *
 * @private
 * @type {Object.<string, Array.<string>>}
 */
var browserMap = {
    gc: [
        'chrome',
        'chromium',
        'silk',
        'yandex',
        'maxthon',
        'chrome headless',
        'chrome webview',
    ],
    edge: ['edge'],
    ie: ['internet explorer', 'iemobile'],
    ff: ['firefox', 'iceweasel'],
    opera: ['opera', 'opera mobi', 'opera tablet'],
    safari: ['safari', 'mobile safari', 'webkit'],
    ucbrowser: ['uc browser'],
    samsung: ['samsung browser'],
    facebook: ['facebook in-app browser'],
};
/**
 * Special-case device model name normalizations.
 * The values here are valid values of the `device` dimension (see feature_device).
 */
var deviceModelNormalizationMap = {
    iPhone: 'iphone',
    iPad: 'ipad',
};
exports.default = {
    parseUA,
};
