"use strict";
// Copyright 2017-2020 @polkadot/metadata 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 createType_1 = require("../../types/codec/create/createType");
const Struct_1 = __importDefault(require("../../types/codec/Struct"));
const util_1 = require("@polkadot/util");
const MagicNumber_1 = __importDefault(require("./MagicNumber"));
const toV1_1 = __importDefault(require("./v0/toV1"));
const toV2_1 = __importDefault(require("./v1/toV2"));
const toV3_1 = __importDefault(require("./v2/toV3"));
const toV4_1 = __importDefault(require("./v3/toV4"));
const toV5_1 = __importDefault(require("./v4/toV5"));
const toV6_1 = __importDefault(require("./v5/toV6"));
const toV7_1 = __importDefault(require("./v6/toV7"));
const toV8_1 = __importDefault(require("./v7/toV8"));
const toV9_1 = __importDefault(require("./v8/toV9"));
const toV10_1 = __importDefault(require("./v9/toV10"));
const toV11_1 = __importDefault(require("./v10/toV11"));
const toLatest_1 = __importDefault(require("./v11/toLatest"));
const util_2 = require("./util");
/**
 * @name MetadataVersioned
 * @description
 * The versioned runtime metadata as a decoded structure
 */
class MetadataVersioned extends Struct_1.default {
    constructor(registry, value) {
        super(registry, {
            magicNumber: MagicNumber_1.default,
            metadata: 'MetadataAll'
        }, value);
        this._converted = new Map();
        registry.setMetadata(this);
    }
    assertVersion(version) {
        util_1.assert(this.version <= version, `Cannot convert metadata from v${this.version} to v${version}`);
        return this.version === version;
    }
    getVersion(version, fromPrev) {
        const asCurr = `asV${version}`;
        const asPrev = `asV${version - 1}`;
        if (this.assertVersion(version)) {
            return this.metadata[asCurr];
        }
        if (!this._converted.has(version)) {
            this._converted.set(version, fromPrev(this.registry, this[asPrev]));
        }
        return this._converted.get(version);
    }
    /**
     * @description Returns the wrapped metadata as a limited calls-only (latest) version
     */
    get asCallsOnly() {
        return new MetadataVersioned(this.registry, {
            magicNumber: this.magicNumber,
            metadata: createType_1.createType(this.registry, 'MetadataAll', util_2.toCallsOnly(this.registry, this.asLatest), this.version)
        });
    }
    /**
     * @description Returns the wrapped metadata as a V0 object
     */
    get asV0() {
        this.assertVersion(0);
        return this.metadata.asV0;
    }
    /**
     * @description Returns the wrapped values as a V1 object
     */
    get asV1() {
        return this.getVersion(1, toV1_1.default);
    }
    /**
     * @description Returns the wrapped values as a V2 object
     */
    get asV2() {
        return this.getVersion(2, toV2_1.default);
    }
    /**
     * @description Returns the wrapped values as a V3 object
     */
    get asV3() {
        return this.getVersion(3, toV3_1.default);
    }
    /**
     * @description Returns the wrapped values as a V4 object
     */
    get asV4() {
        return this.getVersion(4, toV4_1.default);
    }
    /**
     * @description Returns the wrapped values as a V5 object
     */
    get asV5() {
        return this.getVersion(5, toV5_1.default);
    }
    /**
     * @description Returns the wrapped values as a V6 object
     */
    get asV6() {
        return this.getVersion(6, toV6_1.default);
    }
    /**
     * @description Returns the wrapped values as a V7 object
     */
    get asV7() {
        return this.getVersion(7, toV7_1.default);
    }
    /**
     * @description Returns the wrapped values as a V8 object
     */
    get asV8() {
        return this.getVersion(8, toV8_1.default);
    }
    /**
     * @description Returns the wrapped values as a V9 object
     */
    get asV9() {
        return this.getVersion(9, toV9_1.default);
    }
    /**
     * @description Returns the wrapped values as a V10 object
     */
    get asV10() {
        return this.getVersion(10, toV10_1.default);
    }
    /**
     * @description Returns the wrapped values as a V10 object
     */
    get asV11() {
        return this.getVersion(11, toV11_1.default);
    }
    /**
     * @description Returns the wrapped values as a latest version object
     */
    get asLatest() {
        // This is non-existent & latest - applied here to do the module-specific type conversions
        return this.getVersion(12, toLatest_1.default);
    }
    /**
     * @description
     */
    get magicNumber() {
        return this.get('magicNumber');
    }
    /**
     * @description the metadata wrapped
     */
    get metadata() {
        return this.get('metadata');
    }
    /**
     * @description the metadata version this structure represents
     */
    get version() {
        return this.metadata.index;
    }
    getUniqTypes(throwError) {
        return util_2.getUniqTypes(this.registry, this.asLatest, throwError);
    }
}
exports.default = MetadataVersioned;
