import { HexString, Address, ContractState, CallContractParams, CallContractResult, SignExecuteContractMethodParams, SignExecuteScriptTxResult, NetworkId } from '@alephium/web3';

declare namespace RecordTypes {
    type Fields = {
        registrar: HexString;
        owner: Address;
        ttl: bigint;
        manager: Address;
    };
    type State = ContractState<Fields>;
    interface CallMethodTable {
        getOwner: {
            params: Omit<CallContractParams<{}>, "args">;
            result: CallContractResult<Address>;
        };
        setOwner: {
            params: CallContractParams<{
                newOwner: Address;
                newManager: Address;
            }>;
            result: CallContractResult<null>;
        };
        getManager: {
            params: Omit<CallContractParams<{}>, "args">;
            result: CallContractResult<Address>;
        };
        getTTL: {
            params: Omit<CallContractParams<{}>, "args">;
            result: CallContractResult<bigint>;
        };
        setTTL: {
            params: CallContractParams<{
                newTTL: bigint;
            }>;
            result: CallContractResult<null>;
        };
        destroy: {
            params: Omit<CallContractParams<{}>, "args">;
            result: CallContractResult<null>;
        };
    }
    type CallMethodParams<T extends keyof CallMethodTable> = CallMethodTable[T]["params"];
    type CallMethodResult<T extends keyof CallMethodTable> = CallMethodTable[T]["result"];
    type MultiCallParams = Partial<{
        [Name in keyof CallMethodTable]: CallMethodTable[Name]["params"];
    }>;
    type MultiCallResults<T extends MultiCallParams> = {
        [MaybeName in keyof T]: MaybeName extends keyof CallMethodTable ? CallMethodTable[MaybeName]["result"] : undefined;
    };
    interface SignExecuteMethodTable {
        getOwner: {
            params: Omit<SignExecuteContractMethodParams<{}>, "args">;
            result: SignExecuteScriptTxResult;
        };
        setOwner: {
            params: SignExecuteContractMethodParams<{
                newOwner: Address;
                newManager: Address;
            }>;
            result: SignExecuteScriptTxResult;
        };
        getManager: {
            params: Omit<SignExecuteContractMethodParams<{}>, "args">;
            result: SignExecuteScriptTxResult;
        };
        getTTL: {
            params: Omit<SignExecuteContractMethodParams<{}>, "args">;
            result: SignExecuteScriptTxResult;
        };
        setTTL: {
            params: SignExecuteContractMethodParams<{
                newTTL: bigint;
            }>;
            result: SignExecuteScriptTxResult;
        };
        destroy: {
            params: Omit<SignExecuteContractMethodParams<{}>, "args">;
            result: SignExecuteScriptTxResult;
        };
    }
    type SignExecuteMethodParams<T extends keyof SignExecuteMethodTable> = SignExecuteMethodTable[T]["params"];
    type SignExecuteMethodResult<T extends keyof SignExecuteMethodTable> = SignExecuteMethodTable[T]["result"];
}

type Profile = {
    name: string;
    imgUri: string;
};
type ANSNetwork = Exclude<NetworkId, "devnet">;

declare class ANS {
    private web3;
    private config;
    private primaryRegistrar;
    private profileRegistrar;
    private enableLogs;
    constructor(networkId: ANSNetwork, enableLogs?: boolean, customNodeUrl?: string, customExplorerUrl?: string);
    private normalize;
    private getPrimaryRecordContractId;
    private getPrimaryRecordContractAddress;
    /**
     * Get a profile for an account.
     * @param {string} owner - The owner address for the profile.
     * @example <caption>Example usage of `getProfile`</caption>
     * // returns {name: "...", imgUri: "..."}
     * // if name exists, undefined otherwise
     * await ans.getProfile("18sY5...SFuCn");
     * @returns {Promise<Profile | undefined>} profile - The profile for the account.
     */
    getProfile(owner: string): Promise<Profile | undefined>;
    /**
     * Get a record for a name.
     * @param {string} name - The name for the record.
     * @example <caption>Example usage of `getRecord`</caption>
     * // returns {owner: ..., manager: ..., ttl: ...}
     * // if name exists, undefined otherwise
     * await ans.getRecord("name.alph");
     * @returns {Promise<RecordTypes.Fields | undefined>} record - The record for the name.
     */
    getRecord(name: string): Promise<RecordTypes.Fields | undefined>;
    /**
     * Resolve a name.
     * @param {string} name - The name to be resolved.
     * @example <caption>Example usage of `resolveName`</caption>
     * // returns the resolved address string
     * // if name exists, undefined otherwise
     * await ans.resolveName("name.alph");
     * @returns {Promise<string | undefined>} address - The resolved address.
     */
    resolveName(name: string): Promise<string | undefined>;
}

export { ANS };
