"use strict";
// Copyright 2017-2020 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = require("@polkadot/util");
const Enum_1 = __importDefault(require("../codec/Enum"));
const createType_1 = require("../codec/create/createType");
function decodeDataU8a(registry, value) {
    if (!value.length) {
        return [undefined, undefined];
    }
    const indicator = value[0];
    if (indicator === 0) {
        return [null, 0];
    }
    else if (indicator >= 1 && indicator <= 33) {
        const length = indicator - 1;
        const data = value.subarray(1, length + 1);
        // in this case, we are passing a Raw back (since we have no length)
        return [createType_1.createType(registry, 'Raw', data), 1];
    }
    else if (indicator >= 34 && indicator <= 37) {
        return [value.subarray(1, 32 + 1), indicator - 32]; // 34 becomes 2
    }
    throw new Error(`Unable to decode Data, invalid indicator byte ${indicator}`);
}
function decodeData(registry, value) {
    if (!value) {
        return [undefined, undefined];
    }
    else if (util_1.isString(value)) {
        return decodeDataU8a(registry, util_1.u8aToU8a(value));
    }
    else if (util_1.isU8a(value)) {
        return decodeDataU8a(registry, value);
    }
    // assume we have an Enum or an  object input, handle this via the normal Enum decoding
    return [value, undefined];
}
/**
 * @name Data
 * @description
 * A [[Data]] container with node, raw or hashed data
 */
class Data extends Enum_1.default {
    constructor(registry, value) {
        super(registry, {
            None: 'Null',
            Raw: 'Bytes',
            BlakeTwo256: 'H256',
            Sha256: 'H256',
            Keccak256: 'H256',
            ShaThree256: 'H256' // 5
        }, ...decodeData(registry, value));
    }
    get asRaw() {
        return this.raw;
    }
    get asSha256() {
        return this.raw;
    }
    get isRaw() {
        return this.index === 1;
    }
    get isSha256() {
        return this.index === 3;
    }
    /**
     * @description The encoded length
     */
    get encodedLength() {
        return this.toU8a().length;
    }
    /**
     * @description Encodes the value as a Uint8Array as per the SCALE specifications
     */
    toU8a() {
        if (this.index === 0) {
            return new Uint8Array(1);
        }
        else if (this.index === 1) {
            // don't add the length, just the data
            const data = this.raw.toU8a(true);
            const length = Math.min(data.length, 32);
            const u8a = new Uint8Array(length + 1);
            u8a.set([data.length + 1], 0);
            u8a.set(data.subarray(0, length), 1);
            return u8a;
        }
        // otherwise we simply have a hash
        const u8a = new Uint8Array(33);
        u8a.set([this.index + 32], 0);
        u8a.set(this.raw.toU8a(), 1);
        return u8a;
    }
}
exports.default = Data;
