/*
 * noVNC: HTML5 VNC client
 * Copyright (C) 2019 The noVNC Authors
 * Licensed under MPL 2.0 (see LICENSE.txt)
 *
 * See README.md for usage and integration instructions.
 *
 * Browser feature support detection
 */


// Touch detection
let isTouchDevice = ('ontouchstart' in document.documentElement) ||
                                 // requried for Chrome debugger
                                 (document.ontouchstart !== undefined) ||
                                 // required for MS Surface
                                 (navigator.maxTouchPoints > 0) ||
                                 (navigator.msMaxTouchPoints > 0);
window.addEventListener('touchstart', function onFirstTouch() {
    isTouchDevice = true;
    window.removeEventListener('touchstart', onFirstTouch, false);
}, false);


// The goal is to find a certain physical width, the devicePixelRatio
// brings us a bit closer but is not optimal.
let dragThreshold = 10 * (window.devicePixelRatio || 1);

let _supportsCursorURIs = false;

try {
    const target = document.createElement('canvas');
    target.style.cursor = 'url("data:image/x-icon;base64,AAACAAEACAgAAAIAAgA4AQAAFgAAACgAAAAIAAAAEAAAAAEAIAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAA==") 2 2, default';

    if (target.style.cursor.indexOf("url") === 0) {
        Log.Info("Data URI scheme cursor supported");
        _supportsCursorURIs = true;
    } else {
        Log.Warn("Data URI scheme cursor not supported");
    }
} catch (exc) {
    Log.Error("Data URI scheme cursor test exception: " + exc);
}

const supportsCursorURIs = _supportsCursorURIs;

let _hasScrollbarGutter = true;
try {
    // Create invisible container
    const container = document.createElement('div');
    container.style.visibility = 'hidden';
    container.style.overflow = 'scroll'; // forcing scrollbars
    document.body.appendChild(container);

    // Create a div and place it in the container
    const child = document.createElement('div');
    container.appendChild(child);

    // Calculate the difference between the container's full width
    // and the child's width - the difference is the scrollbars
    const scrollbarWidth = (container.offsetWidth - child.offsetWidth);

    // Clean up
    container.parentNode.removeChild(container);

    _hasScrollbarGutter = scrollbarWidth != 0;
} catch (exc) {
    Log.Error("Scrollbar test exception: " + exc);
}
const hasScrollbarGutter = _hasScrollbarGutter;

/*
 * The functions for detection of platforms and browsers below are exported
 * but the use of these should be minimized as much as possible.
 *
 * It's better to use feature detection than platform detection.
 */

/* OS */

function isMac() {
    return !!(/mac/i).exec(navigator.platform);
}

function isWindows() {
    return !!(/win/i).exec(navigator.platform);
}

function isIOS() {
    return (!!(/ipad/i).exec(navigator.platform) ||
            !!(/iphone/i).exec(navigator.platform) ||
            !!(/ipod/i).exec(navigator.platform));
}

function isAndroid() {
    /* Android sets navigator.platform to Linux :/ */
    return !!navigator.userAgent.match('Android ');
}

function isChromeOS() {
    /* ChromeOS sets navigator.platform to Linux :/ */
    return !!navigator.userAgent.match(' CrOS ');
}

/* Browser */

function isSafari() {
    return !!navigator.userAgent.match('Safari/...') &&
           !navigator.userAgent.match('Chrome/...') &&
           !navigator.userAgent.match('Chromium/...') &&
           !navigator.userAgent.match('Epiphany/...');
}

function isFirefox() {
    return !!navigator.userAgent.match('Firefox/...') &&
           !navigator.userAgent.match('Seamonkey/...');
}

function isChrome() {
    return !!navigator.userAgent.match('Chrome/...') &&
           !navigator.userAgent.match('Chromium/...') &&
           !navigator.userAgent.match('Edg/...') &&
           !navigator.userAgent.match('OPR/...');
}

function isChromium() {
    return !!navigator.userAgent.match('Chromium/...');
}

function isOpera() {
    return !!navigator.userAgent.match('OPR/...');
}

function isEdge() {
    return !!navigator.userAgent.match('Edg/...');
}

/* Engine */

function isGecko() {
    return !!navigator.userAgent.match('Gecko/...');
}

function isWebKit() {
    return !!navigator.userAgent.match('AppleWebKit/...') &&
           !navigator.userAgent.match('Chrome/...');
}

function isBlink() {
    return !!navigator.userAgent.match('Chrome/...');
}
window.isTouchDevice = isTouchDevice;
window.dragThreshold = dragThreshold;
window._supportsCursorURIs = _supportsCursorURIs;
window.supportsCursorURIs = supportsCursorURIs;
window._hasScrollbarGutter = _hasScrollbarGutter;
window.hasScrollbarGutter = hasScrollbarGutter;
window.isMac = isMac;
window.isWindows = isWindows;
window.isIOS = isIOS;
window.isAndroid = isAndroid;
window.isChromeOS = isChromeOS;
window.isSafari = isSafari;
window.isFirefox = isFirefox;
window.isChromium = isChromium;
window.isOpera = isOpera;
window.isEdge = isEdge;
window.isGecko = isGecko;
window.isWebKit = isWebKit;
window.isBlink = isBlink;

// Create browser object for compatibility
window.browser = {
    isMac: isMac,
    isWindows: isWindows,
    isIOS: isIOS,
    isAndroid: isAndroid,
    isChromeOS: isChromeOS,
    isSafari: isSafari,
    isFirefox: isFirefox,
    isChrome: isChrome,
    isChromium: isChromium,
    isOpera: isOpera,
    isEdge: isEdge,
    isGecko: isGecko,
    isWebKit: isWebKit,
    isBlink: isBlink
};
