"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 Compact_1 = __importDefault(require("./Compact"));
const utils_1 = require("./utils");
const AbstractArray_1 = __importDefault(require("./AbstractArray"));
const MAX_LENGTH = 32768;
/**
 * @name Vec
 * @description
 * This manages codec arrays. Internally it keeps track of the length (as decoded) and allows
 * construction with the passed `Type` in the constructor. It is an extension to Array, providing
 * specific encoding/decoding on top of the base type.
 */
class Vec extends AbstractArray_1.default {
    constructor(registry, Type, value = []) {
        const Clazz = utils_1.typeToConstructor(registry, Type);
        super(registry, ...Vec.decodeVec(registry, Clazz, value));
        this._Type = Clazz;
    }
    /** @internal */
    static decodeVec(registry, Type, value) {
        if (Array.isArray(value)) {
            return value.map((entry, index) => {
                try {
                    return entry instanceof Type
                        ? entry
                        : new Type(registry, entry);
                }
                catch (error) {
                    console.error(`Unable to decode Vec on index ${index}`, error.message);
                    throw error;
                }
            });
        }
        const u8a = util_1.u8aToU8a(value);
        const [offset, length] = Compact_1.default.decodeU8a(u8a);
        util_1.assert(length.lten(MAX_LENGTH), `Vec length ${length.toString()} exceeds ${MAX_LENGTH}`);
        return utils_1.decodeU8a(registry, u8a.subarray(offset), new Array(length.toNumber()).fill(Type));
    }
    static with(Type) {
        return class extends Vec {
            constructor(registry, value) {
                super(registry, Type, value);
            }
        };
    }
    /**
     * @description The type for the items
     */
    get Type() {
        return this._Type.name;
    }
    /**
     * @description Finds the index of the value in the array
     */
    indexOf(_other) {
        // convert type first, this removes overhead from the eq
        const other = _other instanceof this._Type
            ? _other
            : new this._Type(this.registry, _other);
        for (let i = 0; i < this.length; i++) {
            if (other.eq(this[i])) {
                return i;
            }
        }
        return -1;
    }
    /**
     * @description Returns the base runtime type name for this instance
     */
    toRawType() {
        return `Vec<${new this._Type(this.registry).toRawType()}>`;
    }
}
exports.default = Vec;
