"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.
Object.defineProperty(exports, "__esModule", { value: true });
const known_1 = require("../../../types/known");
const types_1 = require("../../../types");
const util_1 = require("@polkadot/util");
// TODO Handle consts as well
/**
 * Find and apply the correct type override
 * @internal
 **/
function setTypeOverride(sectionTypes, type) {
    const override = Object.keys(sectionTypes).find((aliased) => type.eq(aliased));
    if (override) {
        type.setOverride(sectionTypes[override]);
    }
}
/**
 * Apply module-specific type overrides (always be done as part of toLatest)
 * @internal
 **/
function convertCalls(registry, calls, sectionTypes) {
    return calls.map(({ args, documentation, name }) => {
        args.forEach(({ type }) => setTypeOverride(sectionTypes, type));
        return types_1.createType(registry, 'FunctionMetadataLatest', { args, name, documentation });
    });
}
/**
 * Apply module-specific storage type overrides (always part of toLatest)
 * @internal
 **/
function convertStorage(registry, { items, prefix }, sectionTypes) {
    return types_1.createType(registry, 'StorageMetadataLatest', {
        items: items.map(({ documentation, fallback, modifier, name, type }) => {
            let resultType;
            if (type.isMap) {
                resultType = type.asMap.value;
            }
            else if (type.isDoubleMap) {
                resultType = type.asDoubleMap.value;
            }
            else {
                resultType = type.asPlain;
            }
            setTypeOverride(sectionTypes, resultType);
            return types_1.createType(registry, 'StorageEntryMetadataLatest', { documentation, fallback, modifier, name, type });
        }),
        prefix
    });
}
/**
 * Convert the Metadata (which is an alias) to latest - effectively this _always_ get applied to the top-level &
 * most-recent metadata, since it allows us a chance to actually apply call and storage specific type aliasses
 * @internal
 **/
function toLatest(registry, { modules, extrinsic }) {
    return types_1.createType(registry, 'MetadataLatest', {
        modules: modules.map((mod) => {
            const calls = mod.calls.unwrapOr(null);
            const storage = mod.storage.unwrapOr(null);
            const sectionTypes = known_1.getModuleTypes(util_1.stringCamelCase(mod.name.toString()));
            return types_1.createType(registry, 'ModuleMetadataLatest', Object.assign(Object.assign({}, mod), { calls: calls
                    ? convertCalls(registry, calls, sectionTypes)
                    : null, storage: storage
                    ? convertStorage(registry, storage, sectionTypes)
                    : null }));
        }),
        extrinsic
    });
}
exports.default = toLatest;
