/*
 * Copyright the Collabora Online contributors.
 *
 * SPDX-License-Identifier: MPL-2.0
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
/* global L */
var cool;
(function (cool) {
    var RawDelta = /** @class */ (function () {
        function RawDelta(delta, id, isKeyframe) {
            this._delta = delta;
            this._id = id;
            this._isKeyframe = isKeyframe;
        }
        Object.defineProperty(RawDelta.prototype, "length", {
            get: function () {
                return this.delta.length;
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(RawDelta.prototype, "delta", {
            get: function () {
                return this._delta;
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(RawDelta.prototype, "id", {
            get: function () {
                return this._id;
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(RawDelta.prototype, "isKeyframe", {
            get: function () {
                return this._isKeyframe;
            },
            enumerable: false,
            configurable: true
        });
        return RawDelta;
    }());
    cool.RawDelta = RawDelta;
    var CanvasTileUtils = /** @class */ (function () {
        function CanvasTileUtils() {
        }
        CanvasTileUtils.unrle = function (data, width, height, output, outputOffset) {
            if (outputOffset === void 0) { outputOffset = 0; }
            // Byte bashing fun
            var offset = 0;
            for (var y = 0; y < height; ++y) {
                var rleSize = data[offset] + data[offset + 1] * 256;
                offset += 2;
                var rleMask = offset;
                var rleMaskSizeBytes = 256 / 8;
                offset += rleMaskSizeBytes;
                // It would be rather nice to have real 64bit types [!]
                this.lastPixel.fill(0);
                var lastMask = 0;
                var bitToCheck = 256;
                var rleMaskOffset = rleMask;
                var pixOffset = y * width * 4 + outputOffset;
                var pixSrc = offset;
                for (var x = 0; x < width; ++x) {
                    if (bitToCheck > 128) {
                        bitToCheck = 1;
                        lastMask = data[rleMaskOffset++];
                    }
                    if (!(lastMask & bitToCheck)) {
                        // subarray has a significant overhead on Firefox
                        //this.lastPixel.set(data.subarray(pixSrc, pixSrc + 4));
                        this.lastPixel[0] = data[pixSrc];
                        this.lastPixel[1] = data[pixSrc + 1];
                        this.lastPixel[2] = data[pixSrc + 2];
                        this.lastPixel[3] = data[pixSrc + 3];
                        pixSrc += 4;
                    }
                    bitToCheck = bitToCheck << 1;
                    output.set(this.lastPixel, pixOffset);
                    pixOffset += 4;
                }
                offset += rleSize * 4;
            }
            return offset;
        };
        CanvasTileUtils.updateImageFromDeltas = function (imageData, deltas, keyframeDeltaSize, tileSize, debug) {
            if (debug === void 0) { debug = false; }
            var nDelta = 0;
            var offset = keyframeDeltaSize;
            while (offset < deltas.length) {
                if (debug)
                    console.debug('Next delta at ' + offset + ' length ' + (deltas.length - offset));
                var delta = !offset ? deltas : deltas.subarray(offset);
                // Debugging paranoia: if we get this wrong bad things happen.
                var susDeltaSize = tileSize * tileSize * 4;
                if (debug && delta.length >= susDeltaSize) {
                    console.warn('Unusual delta possibly mis-tagged, suspicious size vs. type ' +
                        delta.length +
                        ' vs. ' +
                        susDeltaSize);
                }
                // copy old data to work from:
                var oldData = new Uint8Array(imageData);
                if (debug)
                    console.debug('Applying delta chunk ' +
                        nDelta++ +
                        ' of total size ' +
                        delta.length +
                        ' at stream offset ' +
                        offset);
                // + ' hex: ' + hex2string(delta, delta.length));
                var len = this.applyDeltaChunk(imageData, delta, oldData, tileSize, tileSize, debug);
                if (debug)
                    console.debug('Applied delta chunk of size ' + len);
                offset += len;
            }
        };
        CanvasTileUtils.applyDeltaChunk = function (imgData, delta, oldData, width, height, debug) {
            if (debug === void 0) { debug = false; }
            var pixSize = width * height * 4;
            var offset = 0;
            // Green-tinge the old-Data ...
            if (0) {
                for (var i_1 = 0; i_1 < pixSize; ++i_1)
                    oldData[i_1 * 4 + 1] = 128;
            }
            // wipe to grey.
            if (0) {
                for (var i_2 = 0; i_2 < pixSize * 4; ++i_2)
                    imgData[i_2] = 128;
            }
            // Apply delta.
            var i = 0;
            for (var stop_1 = false; i < delta.length && !stop_1;) {
                switch (delta[i]) {
                    case 99: {
                        // 'c': // copy row
                        var count = delta[i + 1];
                        var srcRow = delta[i + 2];
                        var destRow = delta[i + 3];
                        if (debug)
                            console.debug('[' +
                                i +
                                ']: copy ' +
                                count +
                                ' row(s) ' +
                                srcRow +
                                ' to ' +
                                destRow);
                        i += 4;
                        for (var cnt = 0; cnt < count; ++cnt) {
                            var src = (srcRow + cnt) * width * 4;
                            var dest = (destRow + cnt) * width * 4;
                            for (var j = 0; j < width * 4; ++j) {
                                imgData[dest + j] = oldData[src + j];
                            }
                        }
                        break;
                    }
                    case 100: {
                        // 'd': // new run
                        var destRow = delta[i + 1];
                        var destCol = delta[i + 2];
                        var span = delta[i + 3];
                        offset = destRow * width * 4 + destCol * 4;
                        if (debug)
                            console.debug('[' +
                                i +
                                ']: apply new span of size ' +
                                span +
                                ' at pos ' +
                                destCol +
                                ', ' +
                                destRow +
                                ' into delta at byte: ' +
                                offset);
                        i += 4;
                        span *= 4;
                        for (var j = 0; j < span; ++j)
                            imgData[offset++] = delta[i + j];
                        i += span;
                        // imgData.data[offset - 2] = 256; // debug - blue terminator
                        break;
                    }
                    case 116: {
                        // 't': // terminate delta new one next
                        stop_1 = true;
                        i++;
                        break;
                    }
                    default: {
                        console.error('[' + i + ']: ERROR: Unknown delta code ' + delta[i]);
                        i = delta.length;
                        break;
                    }
                }
            }
            return i;
        };
        CanvasTileUtils.lastPixel = new Uint8Array(4);
        return CanvasTileUtils;
    }());
    cool.CanvasTileUtils = CanvasTileUtils;
})(cool || (cool = {})); // namespace cool
