"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const EventEmitter = require('events').EventEmitter;
const isEqual = require('lodash.isequal');
const YUVBuffer = require('yuv-buffer');
const YUVCanvas = require('yuv-canvas');

/* contentMode
* - 0: Cropped mode. Uniformly scale the video until it fills the visible boundaries (cropped). One dimension of the video may have clipped contents.
* - 1: Fit mode. Uniformly scale the video until one of its dimension fits the boundary (zoomed to fit). Areas that are not filled due to the disparity
* in the aspect ratio will be filled with black.
*/
class Renderer {
    constructor() {
        this.cacheCanvasOpts = {};
        this.yuv = {};
        this.event = new EventEmitter();
        this.ready = false;
        this.contentMode = 1;
        this.container = {};
        this.canvas = {};
        this.element = {};
    }
    getView() {
        return this.element;
    }
    _calcZoom(vertical = false, contentMode = 0, width, height, clientWidth, clientHeight) {
        let localRatio = clientWidth / clientHeight;
        let tempRatio = width / height;
        if (isNaN(localRatio) || isNaN(tempRatio)) {
            return 1;
        }
        if (!contentMode) {
            if (vertical) {
                return localRatio > tempRatio ?
                    clientHeight / height : clientWidth / width;
            }
            else {
                return localRatio < tempRatio ?
                    clientHeight / height : clientWidth / width;
            }
        }
        else {
            if (vertical) {
                return localRatio < tempRatio ?
                    clientHeight / height : clientWidth / width;
            }
            else {
                return localRatio > tempRatio ?
                    clientHeight / height : clientWidth / width;
            }
        }
    }
    bind(element) {
        this.element = element;
        let container = document.createElement('div');
        Object.assign(container.style, {
            width: '100%',
            height: '100%',
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center'
        });
        this.container = container;
        element.appendChild(this.container);
        this.canvas = document.createElement('canvas');
        this.container.appendChild(this.canvas);
        this.yuv = YUVCanvas.attach(this.canvas, { webGL: false });
    }
    unbind() {
        this.container && this.container.removeChild(this.canvas);
        this.element && this.element.removeChild(this.container);
        this.yuv = null;
        this.element = null;
        this.canvas = null;
        this.view = null;
    }
    refreshCanvas() {
    }
    updateCanvas(options = {
        width: 0,
        height: 0,
        rotation: 0,
        mirrorView: false,
        contentMode: 0,
        clientWidth: 0,
        clientHeight: 0,
    }) {
        if (isEqual(this.cacheCanvasOpts, options)) {
            return;
        }
        this.cacheCanvasOpts = Object.assign({}, options);
        if (options.rotation === 0 || options.rotation === 180) {
            this.canvas.width = options.width;
            this.canvas.height = options.height;
        }
        else if (options.rotation === 90 || options.rotation === 270) {
            this.canvas.height = options.width;
            this.canvas.width = options.height;
        }
        else {
            throw new Error('Invalid value for rotation. Only support 0, 90, 180, 270');
        }
        this.canvas.style.zoom = this._calcZoom(options.rotation === 90 || options.rotation === 270, options.contentMode, options.width, options.height, options.clientWidth, options.clientHeight);
        if (options.mirrorView) {
            this.canvas.style.transform = 'rotateY(180deg)';
        }
    }
    drawFrame(imageData) {
        if (!this.ready) {
            this.ready = true;
            this.event.emit('ready');
        }
        let mirror = 0;
        let contentWidth = imageData.width;
        let contentHeight = imageData.height;
        let left = 0;
        let top = 0;
        let right = 0;
        let bottom = 0;
        let rotation = imageData.rotation;
        let ts = imageData.timestamp;
        let width = contentWidth + left + right;
        let height = contentHeight + top + bottom;
        this.updateCanvas({
            width, height, rotation,
            mirrorView: mirror,
            contentMode: this.contentMode,
            clientWidth: this.container.clientWidth,
            clientHeight: this.container.clientHeight,
        });
        let format = YUVBuffer.format({
            width,
            height,
            chromaWidth: width / 2,
            chromaHeight: height / 2
        });
        let y = YUVBuffer.lumaPlane(format, imageData.yUint8Array);
        let u = YUVBuffer.chromaPlane(format, imageData.uUint8Array);
        let v = YUVBuffer.chromaPlane(format, imageData.vUint8Array);
        let frame = YUVBuffer.frame(format, y, u, v);
        this.yuv.drawFrame(frame);
    }
    setContentMode(mode = 0) {
        this.contentMode = mode;
    }
}
exports.default = Renderer;
