"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 utils_1 = require("./utils");
const AbstractArray_1 = __importDefault(require("./AbstractArray"));
/**
 * @name Tuple
 * @description
 * A Tuple defines an anonymous fixed-length array, where each element has its
 * own type. It extends the base JS `Array` object.
 */
class Tuple extends AbstractArray_1.default {
    constructor(registry, Types, value) {
        const Clazzes = Array.isArray(Types)
            ? Types.map((type) => utils_1.typeToConstructor(registry, type))
            : utils_1.mapToTypeMap(registry, Types);
        super(registry, ...Tuple.decodeTuple(registry, Clazzes, value));
        this._Types = Clazzes;
    }
    /** @internal */
    static decodeTuple(registry, _Types, value) {
        if (util_1.isU8a(value)) {
            return utils_1.decodeU8a(registry, value, _Types);
        }
        else if (util_1.isHex(value)) {
            return Tuple.decodeTuple(registry, _Types, util_1.hexToU8a(value));
        }
        const Types = Array.isArray(_Types)
            ? _Types
            : Object.values(_Types);
        return Types.map((Type, index) => {
            try {
                return new Type(registry, value && value[index]);
            }
            catch (error) {
                throw new Error(`Tuple: failed on ${index}:: ${error.message}`);
            }
        });
    }
    static with(Types) {
        return class extends Tuple {
            constructor(registry, value) {
                super(registry, Types, value);
            }
        };
    }
    /**
     * @description The length of the value when encoded as a Uint8Array
     */
    get encodedLength() {
        return this.reduce((length, entry) => {
            length += entry.encodedLength;
            return length;
        }, 0);
    }
    /**
     * @description The types definition of the tuple
     */
    get Types() {
        return Array.isArray(this._Types)
            ? this._Types.map((Type) => new Type(this.registry).toRawType())
            : Object.keys(this._Types);
    }
    /**
     * @description Returns the base runtime type name for this instance
     */
    toRawType() {
        const types = (Array.isArray(this._Types)
            ? this._Types
            : Object.values(this._Types)).map((Type) => new Type(this.registry).toRawType());
        return `(${types.join(',')})`;
    }
    /**
     * @description Returns the string representation of the value
     */
    toString() {
        // Overwrite the default toString representation of Array.
        return JSON.stringify(this.toJSON());
    }
    /**
     * @description Encodes the value as a Uint8Array as per the SCALE specifications
     * @param isBare true when the value has none of the type-specific prefixes (internal)
     */
    toU8a(isBare) {
        return util_1.u8aConcat(...this.map((entry) => entry.toU8a(isBare)));
    }
}
exports.default = Tuple;
