import { IsDocumentAvailable } from "../Misc/domManagement.js";
import { AbstractEngine } from "./abstractEngine.js";
import { EngineStore } from "./engineStore.js";
/** @internal */
function DisableTouchAction(canvas) {
    if (!canvas || !canvas.setAttribute) {
        return;
    }
    canvas.setAttribute("touch-action", "none");
    canvas.style.touchAction = "none";
    canvas.style.webkitTapHighlightColor = "transparent";
}
/** @internal */
export function _CommonInit(commonEngine, canvas, creationOptions) {
    commonEngine._onCanvasFocus = () => {
        commonEngine.onCanvasFocusObservable.notifyObservers(commonEngine);
    };
    commonEngine._onCanvasBlur = () => {
        commonEngine.onCanvasBlurObservable.notifyObservers(commonEngine);
    };
    commonEngine._onCanvasContextMenu = (evt) => {
        if (commonEngine.disableContextMenu) {
            evt.preventDefault();
        }
    };
    canvas.addEventListener("focus", commonEngine._onCanvasFocus);
    canvas.addEventListener("blur", commonEngine._onCanvasBlur);
    canvas.addEventListener("contextmenu", commonEngine._onCanvasContextMenu);
    commonEngine._onBlur = () => {
        if (commonEngine.disablePerformanceMonitorInBackground) {
            commonEngine.performanceMonitor.disable();
        }
        commonEngine._windowIsBackground = true;
    };
    commonEngine._onFocus = () => {
        if (commonEngine.disablePerformanceMonitorInBackground) {
            commonEngine.performanceMonitor.enable();
        }
        commonEngine._windowIsBackground = false;
    };
    commonEngine._onCanvasPointerOut = (ev) => {
        // Check that the element at the point of the pointer out isn't the canvas and if it isn't, notify observers
        // Note: This is a workaround for a bug with Safari
        if (document.elementFromPoint(ev.clientX, ev.clientY) !== canvas) {
            commonEngine.onCanvasPointerOutObservable.notifyObservers(ev);
        }
    };
    const hostWindow = commonEngine.getHostWindow(); // it calls IsWindowObjectExist()
    if (hostWindow && typeof hostWindow.addEventListener === "function") {
        hostWindow.addEventListener("blur", commonEngine._onBlur);
        hostWindow.addEventListener("focus", commonEngine._onFocus);
    }
    canvas.addEventListener("pointerout", commonEngine._onCanvasPointerOut);
    if (!creationOptions.doNotHandleTouchAction) {
        DisableTouchAction(canvas);
    }
    // Create Audio Engine if needed.
    if (!AbstractEngine.audioEngine && creationOptions.audioEngine && AbstractEngine.AudioEngineFactory) {
        AbstractEngine.audioEngine = AbstractEngine.AudioEngineFactory(commonEngine.getRenderingCanvas(), commonEngine.getAudioContext(), commonEngine.getAudioDestination());
    }
    if (IsDocumentAvailable()) {
        // Fullscreen
        commonEngine._onFullscreenChange = () => {
            commonEngine.isFullscreen = !!document.fullscreenElement;
            const inputElement = commonEngine.getInputElement();
            // Pointer lock
            if (commonEngine.isFullscreen && commonEngine._pointerLockRequested && inputElement) {
                RequestPointerlock(inputElement);
            }
        };
        document.addEventListener("fullscreenchange", commonEngine._onFullscreenChange, false);
        document.addEventListener("webkitfullscreenchange", commonEngine._onFullscreenChange, false);
        // Pointer lock
        commonEngine._onPointerLockChange = () => {
            commonEngine.isPointerLock = document.pointerLockElement === commonEngine.getInputElement();
        };
        document.addEventListener("pointerlockchange", commonEngine._onPointerLockChange, false);
        document.addEventListener("webkitpointerlockchange", commonEngine._onPointerLockChange, false);
    }
    commonEngine.enableOfflineSupport = AbstractEngine.OfflineProviderFactory !== undefined;
    commonEngine._deterministicLockstep = !!creationOptions.deterministicLockstep;
    commonEngine._lockstepMaxSteps = creationOptions.lockstepMaxSteps || 0;
    commonEngine._timeStep = creationOptions.timeStep || 1 / 60;
}
/** @internal */
export function _CommonDispose(commonEngine, canvas) {
    // Release audio engine
    if (EngineStore.Instances.length === 1 && AbstractEngine.audioEngine) {
        AbstractEngine.audioEngine.dispose();
        AbstractEngine.audioEngine = null;
    }
    // Events
    const hostWindow = commonEngine.getHostWindow(); // it calls IsWindowObjectExist()
    if (hostWindow && typeof hostWindow.removeEventListener === "function") {
        hostWindow.removeEventListener("blur", commonEngine._onBlur);
        hostWindow.removeEventListener("focus", commonEngine._onFocus);
    }
    if (canvas) {
        canvas.removeEventListener("focus", commonEngine._onCanvasFocus);
        canvas.removeEventListener("blur", commonEngine._onCanvasBlur);
        canvas.removeEventListener("pointerout", commonEngine._onCanvasPointerOut);
        canvas.removeEventListener("contextmenu", commonEngine._onCanvasContextMenu);
    }
    if (IsDocumentAvailable()) {
        document.removeEventListener("fullscreenchange", commonEngine._onFullscreenChange);
        document.removeEventListener("mozfullscreenchange", commonEngine._onFullscreenChange);
        document.removeEventListener("webkitfullscreenchange", commonEngine._onFullscreenChange);
        document.removeEventListener("msfullscreenchange", commonEngine._onFullscreenChange);
        document.removeEventListener("pointerlockchange", commonEngine._onPointerLockChange);
        document.removeEventListener("mspointerlockchange", commonEngine._onPointerLockChange);
        document.removeEventListener("mozpointerlockchange", commonEngine._onPointerLockChange);
        document.removeEventListener("webkitpointerlockchange", commonEngine._onPointerLockChange);
    }
}
/**
 * Get Font size information
 * @param font font name
 * @returns an object containing ascent, height and descent
 */
export function GetFontOffset(font) {
    const text = document.createElement("span");
    text.textContent = "Hg";
    text.style.font = font;
    const block = document.createElement("div");
    block.style.display = "inline-block";
    block.style.width = "1px";
    block.style.height = "0px";
    block.style.verticalAlign = "bottom";
    const div = document.createElement("div");
    div.style.whiteSpace = "nowrap";
    div.appendChild(text);
    div.appendChild(block);
    document.body.appendChild(div);
    let fontAscent = 0;
    let fontHeight = 0;
    try {
        fontHeight = block.getBoundingClientRect().top - text.getBoundingClientRect().top;
        block.style.verticalAlign = "baseline";
        fontAscent = block.getBoundingClientRect().top - text.getBoundingClientRect().top;
    }
    finally {
        document.body.removeChild(div);
    }
    return { ascent: fontAscent, height: fontHeight, descent: fontHeight - fontAscent };
}
/** @internal */
export async function CreateImageBitmapFromSource(engine, imageSource, options) {
    return await new Promise((resolve, reject) => {
        const image = new Image();
        image.onload = () => {
            // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then
            image.decode().then(() => {
                // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then
                engine.createImageBitmap(image, options).then((imageBitmap) => {
                    resolve(imageBitmap);
                });
            });
        };
        image.onerror = () => {
            // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
            reject(`Error loading image ${image.src}`);
        };
        image.src = imageSource;
    });
}
/** @internal */
export function ResizeImageBitmap(engine, image, bufferWidth, bufferHeight) {
    const canvas = engine.createCanvas(bufferWidth, bufferHeight);
    const context = canvas.getContext("2d");
    if (!context) {
        throw new Error("Unable to get 2d context for resizeImageBitmap");
    }
    context.drawImage(image, 0, 0);
    // Create VertexData from map data
    // Cast is due to wrong definition in lib.d.ts from ts 1.3 - https://github.com/Microsoft/TypeScript/issues/949
    const buffer = context.getImageData(0, 0, bufferWidth, bufferHeight).data;
    return buffer;
}
/**
 * Ask the browser to promote the current element to fullscreen rendering mode
 * @param element defines the DOM element to promote
 */
export function RequestFullscreen(element) {
    const requestFunction = element.requestFullscreen || element.webkitRequestFullscreen;
    if (!requestFunction) {
        return;
    }
    requestFunction.call(element);
}
/**
 * Asks the browser to exit fullscreen mode
 */
export function ExitFullscreen() {
    const anyDoc = document;
    if (document.exitFullscreen) {
        // eslint-disable-next-line @typescript-eslint/no-floating-promises
        document.exitFullscreen();
    }
    else if (anyDoc.webkitCancelFullScreen) {
        anyDoc.webkitCancelFullScreen();
    }
}
/**
 * Ask the browser to promote the current element to pointerlock mode
 * @param element defines the DOM element to promote
 */
export function RequestPointerlock(element) {
    if (element.requestPointerLock) {
        // In some browsers, requestPointerLock returns a promise.
        // Handle possible rejections to avoid an unhandled top-level exception.
        const promise = element.requestPointerLock();
        if (promise instanceof Promise) {
            promise
                // eslint-disable-next-line github/no-then
                .then(() => {
                element.focus();
            })
                // eslint-disable-next-line github/no-then
                .catch(() => { });
        }
        else {
            element.focus();
        }
    }
}
/**
 * Asks the browser to exit pointerlock mode
 */
export function ExitPointerlock() {
    if (document.exitPointerLock) {
        document.exitPointerLock();
    }
}
//# sourceMappingURL=engine.common.js.map