declare module "openpgp" {
    interface keys {
        decrypt: ( pass: string ) => void
    }
    interface keyIds {
        
    }
    interface verifyOption {
      message:string, 
      publicKeys: key[]
    }
    interface verifyResult {
        data: string;
        signatures: any;
    }
    enum EArmor {
        multipart_section,
        multipart_last,
        signed,
        message,
        public_key,
        private_key
    }
    interface ESymmetric {
        plaintext
        idea
        tripledes
        cast5
        blowfish
        aes128
        aes192
        aes256
        twofish
    }
    interface hash {
        
    }
    interface ISignature {
        cert_generic: string;
    }
    interface IEnums {
        armor: EArmor;
        signature:ISignature;
        keyFlags:IKeyFlags;
        symmetric: ESymmetric;
        hash:any;
        compression:any
    }
    interface key {
        
        /**
         * Reads an OpenPGP armored text and returns one or multiple key objects
         * @param {String} armoredText text to be parsed
         * @return {{keys: Array<module:key~Key>, err: (Array<Error>|null)}} result object with key and error arrays
         * @static
         */
        readArmored: (armoredText: string|string[]) => { 
            keys: keys[]
            decrypt: ( pass: string ) => void;
        };
        Key:any
    }
    interface messages {
        
        /**
         * Returns the key IDs of the keys to which the session key is encrypted
         * @return {Array<module:type/keyid>} array of keyid objects
         */
        getEncryptionKeyIds: () => keyIds[];
    }
    interface message {
        
        /**
         * reads an OpenPGP armored message and returns a message object
         * @param {String} armoredText text to be parsed
         * @return {module:message~Message} new message object
         * @static
         */
        readArmored: (armoredText: string) => messages;
    }
    interface DecryptionOption {
        message: messages;
        privateKey?: keys;
        publicKeys?: keys | keys[];
        sessionKey?: Object;
        password?: string;
        format?: string;     //   as 'utf8' or 'binary'
        
    }
    interface EncryptionOption {
        data: string | Uint8Array;
        publicKeys: keys | keys[]
    }
    interface decryptResult {
        then: (plaintext) => decryptResult;
        catch: (callBack: (err: Error ) => void) => void;
    }
    interface IKeyFlags {
        certify_keys:any;
        sign_data:any;
    }
    interface ISignature {
        new ():ISignature;
        signatureType: string;
        hashAlgorithm: number;
        publicKeyAlgorithm: number;
        keyFlags: any[];
        preferredSymmetricAlgorithms: string[]
        preferredHashAlgorithms:any[]
        preferredCompressionAlgorithms: any[];
        sign:any
    }
    interface IList {
        new () : IList;
        push: (any) => void;
        read: (msg: string) => PackageDetail;
    }
    interface PackageDetail {
        
    }
    interface IPacket {
        Signature: ISignature;
        List:IList
    }
    interface generateKeyOption {
        userIds: {
            name: string;
            email: string;
        };
        passphrase?: string;
        numBits?: number; // should be 2048 or 4096
        unlocked?: boolean; //   If the returned secret part of the generated key is unlocked
    }
    interface IKeyringPublicKeys {
        importKey: (key: string) => void;
        getForId: (id: string) =>keys;
        
    }
    interface IKeyring {
        new (): IKeyring;
        clear(): void;
        store(): void;
        publicKeys: IKeyringPublicKeys;
        getKeysForId: (id: string) => keys;
    }
	interface IConfig {
		aead_protect: boolean;
	}
    interface Iopenpgp {
        key: key;
        message: message;
        packet:IPacket;
        enums: IEnums;
        Keyring: IKeyring;
        config:IConfig;
        /**
         * Decrypts a message with the user's private key, a session key or a password. Either a private key,
         *   a session key or a password must be specified.
         * @param  {Message} message             the message object with the encrypted data
         * @param  {Key} privateKey              (optional) private key with decrypted secret key data or session key
         * @param  {Key|Array<Key>} publicKeys   (optional) array of public keys or single key, to verify signatures
         * @param  {Object} sessionKey           (optional) session key in the form: { data:Uint8Array, algorithm:String }
         * @param  {String} password             (optional) single password to decrypt the message
         * @param  {String} format               (optional) return data format either as 'utf8' or 'binary'
         * @return {Promise<Object>}             decrypted and verified message in the form:
         *                                         { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] }
         * @static
         */
        decrypt: (decryptionOption: DecryptionOption) => decryptResult;
        
        /**
         * Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords
         *   must be specified. If private keys are specified, those will be used to sign the message.
         * @param  {String|Uint8Array} data           text/data to be encrypted as JavaScript binary string or Uint8Array
         * @param  {Key|Array<Key>} publicKeys        (optional) array of keys or single key, used to encrypt the message
         * @param  {Key|Array<Key>} privateKeys       (optional) private keys for signing. If omitted message will not be signed
         * @param  {String|Array<String>} passwords   (optional) array of passwords or a single password to encrypt the message
         * @param  {String} filename                  (optional) a filename for the literal data packet
         * @param  {Boolean} armor                    (optional) if the return value should be ascii armored or the message object
         * @return {Promise<String|Message>}          encrypted ASCII armored message, or the full Message object if 'armor' is false
         * @static
         */
        encrypt: (encryptionOption: EncryptionOption) => decryptResult;
        
        /**
         * Generates a new OpenPGP key pair. Currently only supports RSA keys. Primary and subkey will be of same type.
         * @param  {Array<Object>} userIds   array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
         * @param  {String} passphrase       (optional) The passphrase used to encrypt the resulting private key
         * @param  {Number} numBits          (optional) number of bits for the key creation. (should be 2048 or 4096)
         * @param  {Boolean} unlocked        (optional) If the returned secret part of the generated key is unlocked
         * @return {Promise<Object>}         The generated key object in the form:
         *                                     { key:Key, privateKeyArmored:String, publicKeyArmored:String }
         * @static
         */
        generateKey: (generateKeyOption: generateKeyOption) => decryptResult;
    
        /**
         * Verifies signatures of cleartext signed message
         * @param  {Key|Array<Key>} publicKeys   array of publicKeys or single key, to verify signatures
         * @param  {CleartextMessage} message    cleartext message object with signatures
         * @return {Promise<Object>}             cleartext with status of verified signatures in the form of:
         *                                         { data:String, signatures: [{ keyid:String, valid:Boolean }] }
         * @static
         */
        
        verify: (verifyOption) => verifyResult;
}
    
    let ex: Iopenpgp;
    
    export = ex;
}
