import { Network } from "./Network";
import { PublicKey } from "./PublicKey";
import { Address } from "./Address";
import { BN } from "./crypto/BN";

/**
 * Instantiate a PrivateKey from a BN, Buffer and WIF.
 *
 * @example
 * ```javascript
 * // generate a new random key
 * var key = PrivateKey();
 *
 * // get the associated address
 * var address = key.toAddress();
 *
 * // encode into wallet export format
 * var exported = key.toWIF();
 *
 * // instantiate from the exported (and saved) private key
 * var imported = PrivateKey.fromWIF(exported);
 * ```
 *
 * @param {string} data - The encoded data in various formats
 * @param {Network|string=} network - a {@link Network} object, or a string with the network name
 * @returns {PrivateKey} A new valid instance of a PrivateKey
 * @constructor
 */
export class PrivateKey {
    constructor(data: string, network: Network | string);

    readonly bn: BN;
    readonly compressed: boolean;
    readonly network: Network;
    readonly publicKey: PublicKey;

    /**
     * Internal helper to instantiate PrivateKey internal `info` object from
     * different kinds of arguments passed to the constructor.
     *
     * @param {*} data
     * @param {Network|string=} network - a {@link Network} object, or a string with the network name
     * @return {Object}
     */
    _classifyArguments(data: any, network: Network | string): any;

    /**
     * Instantiate a PrivateKey from a Buffer with the DER or WIF representation
     *
     * @param {Buffer} arg
     * @param {Network} network
     * @return {PrivateKey}
     */
    static fromBuffer(arg: Buffer, network: Network): PrivateKey;

    /**
     * Instantiate a PrivateKey from a WIF string
     *
     * @function
     * @param {string} str - The WIF encoded private key string
     * @returns {PrivateKey} A new valid instance of PrivateKey
     */
    static fromString(str: string): PrivateKey;

    /**
     * Instantiate a PrivateKey from a plain JavaScript object
     *
     * @param {Object} obj - The output from privateKey.toObject()
     */
    static fromObject(obj: any): void;

    /**
     * Instantiate a PrivateKey from random bytes
     *
     * @param {string=} network - Either "livenet" or "testnet"
     * @returns {PrivateKey} A new valid instance of PrivateKey
     */
    static fromRandom(network?: string): PrivateKey;

    /**
     * Check if there would be any errors when initializing a PrivateKey
     *
     * @param {string} data - The encoded data in various formats
     * @param {string=} network - Either "livenet" or "testnet"
     * @returns {null|Error} An error if exists
     */
    static getValidationError(data: string, network?: string): null | Error;

    /**
     * Check if the parameters are valid
     *
     * @param {string} data - The encoded data in various formats
     * @param {string=} network - Either "livenet" or "testnet"
     * @returns {Boolean} If the private key is would be valid
     */
    static isValid(data: string, network?: string): boolean;

    /**
     * Will output the PrivateKey encoded as hex string
     *
     * @returns {string}
     */
    toString(): string;

    /**
     * Will output the PrivateKey to a WIF string
     *
     * @returns {string} A WIP representation of the private key
     */
    toWIF(): string;

    /**
     * Will return the private key as a BN instance
     *
     * @returns {BN} A BN instance of the private key
     */
    toBigNumber(): BN;

    /**
     * Will return the private key as a BN buffer
     *
     * @returns {Buffer} A buffer of the private key
     */
    toBuffer(): Buffer;

    /**
     * WARNING: This method will not be officially supported until v1.0.0.
     *
     *
     * Will return the private key as a BN buffer without leading zero padding
     *
     * @returns {Buffer} A buffer of the private key
     */
    toBufferNoPadding(): Buffer;

    /**
     * Will return the corresponding public key
     *
     * @returns {PublicKey} A public key generated from the private key
     */
    toPublicKey(): PublicKey;

    /**
     * Will return an address for the private key
     * @param {Network=} network - optional parameter specifying
     * the desired network for the address
     *
     * @returns {Address} An address generated from the private key
     */
    toAddress(network?: Network): Address;

    /**
     * @function
     * @returns {Object} A plain object representation
     */
    toObject(): any;

    /**
     * @function
     * @returns {Object} A plain object representation
     */
    toJSON(): any;

    /**
     * Will return a string formatted for the console
     *
     * @returns {string} Private key
     */
    inspect(): string;
}
