import * as polkadotUtil from '@polkadot/util'
import * as polkadotUtilCrypto from '@polkadot/util-crypto'
import { getTypeDef, createType, Option, Raw } from '@polkadot/types'
import { unwrapStorageType } from '@polkadot/types/primitive/StorageKey'
import { TypeDefInfo } from '@polkadot/types/types'

// function isValidApiUrl(url: string) {
//     const protocol = new URL(url).protocol
//     return protocol == 'ws:' || protocol == 'wss:'
// }

function getCallArgs(moduleMetadata: any, callName: string) {
    const idx = moduleMetadata.calls.find((data: any) => data === callName)
    return idx && moduleMetadata.calls[idx].args
}

function getModules(api: any) {
    return Object.keys(api.query).sort()
}

function parseTypeDef(typeName: string, registry: any) {
    if (!typeName || !registry) return null

    try {
        const typeDef = getTypeDef(typeName)

        // create the type and get the raw
        const type = createType(registry, typeName)
        const raw = type.toRawType()
        const rawTypeDef = getTypeDef(raw)

        return {
            name: typeName,
            type: typeDef,
            rawType: rawTypeDef,
            registry: registry,
        }
    } catch (e) {
        console.error(e)
        return null
    }
}

function storageResultTypeString(registry: any, storageCreatorMeta: any) {
    const typeStr = unwrapStorageType(registry, storageCreatorMeta.type)

    return storageCreatorMeta.modifier.isOptional
        ? `Option<${typeStr}>`
        : typeStr
}

function storageResultString(typeName: string, result: any) {
    if (polkadotUtil.isNull(result) || polkadotUtil.isUndefined(result))
        return '<unknown>'

    if (['Bytes', 'Raw', 'Option<Keys>', 'Keys'].includes(typeName)) {
        return polkadotUtil.u8aToHex(result.toU8a(true))
    }

    if (result instanceof Raw && result.isEmpty) {
        return '<empty>'
    } else if (result instanceof Option && result.isNone) {
        return '<none>'
    }
    return result.toString()
}

module.exports = {
    ...polkadotUtil,
    // isValidApiUrl,
    getCallArgs,
    getModules,
    parseTypeDef,
    storageResultTypeString,
    storageResultString,
    crypto: polkadotUtilCrypto,
}
