"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EndUserBase64Coder = void 0;
const eutypes_1 = require("./eutypes");
class EndUserBase64Coder {
    constructor() {
        this.vendor = 'JSC IIT';
        this.classVersion = 1;
        this.className = 'EndUserBase64Coder';
        this.m_map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        this.m_codes = [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
            80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103,
            104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
            119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47];
    }
    _getTextDecoder() {
        try {
            if (typeof TextDecoder == 'undefined')
                return null;
            var decoder = new TextDecoder('utf-8');
            if (decoder.encoding != 'utf-8')
                return null;
            return decoder;
        }
        catch (e) {
            return null;
        }
    }
    _encodePart(bytes, begin, end) {
        var result = [];
        var tmp, str;
        for (var i = begin; i < end; i += 3) {
            tmp = (bytes[i] << 16) |
                (bytes[i + 1] << 8) |
                (bytes[i + 2]);
            str = this.m_map[(tmp >> 18) & 0x3F] +
                this.m_map[(tmp >> 12) & 0x3F] +
                this.m_map[(tmp >> 6) & 0x3F] +
                this.m_map[tmp & 0x3F];
            result.push(str);
        }
        return result.join('');
    }
    encode(array) {
        var bytes;
        var i, j;
        var tmp;
        var length;
        var str = '';
        bytes = (typeof Uint8Array == 'undefined') ?
            ((typeof eutypes_1.EndUserUint8Array == 'undefined') ?
                array.slice(0) : new eutypes_1.EndUserUint8Array(array)) :
            new Uint8Array(array);
        length = bytes.length;
        if (length == 0)
            return '';
        var decoder = this._getTextDecoder();
        if (decoder != null) {
            // @ts-ignore
            var result = new Uint8Array(parseInt(((length + 2) / 3)) * 4);
            for (i = 0, j = 0; i < length - (length % 3); i += 3, j += 4) {
                tmp = (bytes[i] << 16) |
                    (bytes[i + 1] << 8) |
                    (bytes[i + 2]);
                result[j] = this.m_codes[(tmp >> 18) & 0x3F];
                result[j + 1] = this.m_codes[(tmp >> 12) & 0x3F];
                result[j + 2] = this.m_codes[(tmp >> 6) & 0x3F];
                result[j + 3] = this.m_codes[tmp & 0x3F];
            }
            switch (length % 3) {
                case 1:
                    tmp = (bytes[i] << 16);
                    result[j] = this.m_codes[(tmp >> 18) & 0x3F];
                    result[j + 1] = this.m_codes[(tmp >> 12) & 0x3F];
                    result[j + 2] = 61;
                    result[j + 3] = 61;
                    break;
                case 2:
                    tmp = (bytes[i] << 16) |
                        (bytes[i + 1] << 8);
                    result[j] = this.m_codes[(tmp >> 18) & 0x3F];
                    result[j + 1] = this.m_codes[(tmp >> 12) & 0x3F];
                    result[j + 2] = this.m_codes[(tmp >> 6) & 0x3F];
                    result[j + 3] = 61;
                    break;
            }
            str = decoder.decode(result);
        }
        else {
            var result2 = [];
            var part = null;
            var partLength = 5 * 1024 * 3;
            var baseLength = length - (length % 3);
            // @ts-ignore
            var partsCount = parseInt(baseLength / partLength);
            var lastPart;
            for (i = 0; i < partsCount; i++) {
                part = this._encodePart(bytes, i * partLength, i * partLength + partLength);
                result2.push(part);
            }
            if ((partsCount * partLength) < baseLength) {
                part = this._encodePart(bytes, i * partLength, baseLength);
                result2.push(part);
            }
            switch (length % 3) {
                case 1:
                    tmp = (bytes[length - 1] << 16);
                    lastPart = this.m_map[(tmp >> 18) & 0x3F];
                    lastPart += this.m_map[(tmp >> 12) & 0x3F];
                    lastPart += '=';
                    lastPart += '=';
                    result2.push(lastPart);
                    break;
                case 2:
                    tmp = (bytes[length - 2] << 16) |
                        (bytes[length - 1] << 8);
                    lastPart = this.m_map[(tmp >> 18) & 0x3F];
                    lastPart += this.m_map[(tmp >> 12) & 0x3F];
                    lastPart += this.m_map[(tmp >> 6) & 0x3F];
                    lastPart += '=';
                    result2.push(lastPart);
                    break;
            }
            str = result2.join('');
        }
        return str;
    }
    decode(base64Str) {
        var bytes;
        var bytesLength;
        var i, j, p;
        var base64StrLength;
        var equals;
        var encoded1, encoded2, encoded3, encoded4;
        if ((base64Str == '') || ((base64Str.length & 0x03) > 0)) {
            return (typeof Uint8Array == 'undefined') ?
                ((typeof eutypes_1.EndUserUint8Array == 'undefined') ?
                    [] : new eutypes_1.EndUserUint8Array(0)) :
                (new Uint8Array(0));
        }
        base64StrLength = base64Str.length;
        equals = (base64Str[base64StrLength - 1] == '=') ?
            ((base64Str[base64StrLength - 2] == '=') ? 2 : 1) : 0;
        bytesLength = (base64StrLength / 4) * 3 - equals;
        bytes = (typeof Uint8Array == 'undefined') ?
            ((typeof eutypes_1.EndUserUint8Array == 'undefined') ?
                [] : new eutypes_1.EndUserUint8Array(bytesLength)) :
            new Uint8Array(bytesLength);
        for (i = 0, j = 0, p = 0; i <
            Math.floor((base64StrLength - equals) / 4); i++) {
            encoded1 = this.m_map.indexOf(base64Str[j++]);
            encoded2 = this.m_map.indexOf(base64Str[j++]);
            encoded3 = this.m_map.indexOf(base64Str[j++]);
            encoded4 = this.m_map.indexOf(base64Str[j++]);
            bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
            bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
            bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
        }
        switch (equals) {
            case 2:
                encoded1 = this.m_map.indexOf(base64Str[j]);
                encoded2 = this.m_map.indexOf(base64Str[j + 1]);
                bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
                break;
            case 1:
                encoded1 = this.m_map.indexOf(base64Str[j]);
                encoded2 = this.m_map.indexOf(base64Str[j + 1]);
                encoded3 = this.m_map.indexOf(base64Str[j + 2]);
                bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
                bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
                break;
        }
        return bytes;
    }
}
exports.EndUserBase64Coder = EndUserBase64Coder;
