import {GlobalCrypto} from "./global-crypto";
import { base64 } from "rfc4648";
import * as nacl from 'tweetnacl';

/**
 * THIS IS OUR HANDY LAYER OF THE NATIVE CRYPTO WHAT IS TESTED IN THE login/crpytography.specs.ts
 */

describe('Global Crypto', () => {


    /*it("check the AES_SIV_N0_128_256 encrypt/decrypt", (done)=>{

        let key = crypto.getRandomValues(new Uint8Array(32));
        let plain = crypto.getRandomValues(new Uint8Array(512));

        GlobalCrypto.AES_SIV_N0_128_256_encrypt(plain, key).then(encryptedPlain=>{
            return GlobalCrypto.AES_SIV_N0_128_256_decrypt(encryptedPlain, key).then(decryptedPlain=>{
                expect(base64.stringify(plain) == base64.stringify(decryptedPlain)).toBeTrue();
                done();
            });
        });
    });

    it("check the AES_SIV_N96_128_256 encrypt/decrypt", (done)=>{

        let key = crypto.getRandomValues(new Uint8Array(32));
        let plain = crypto.getRandomValues(new Uint8Array(512));

        GlobalCrypto.AES_SIV_N96_128_256_encrypt(plain, key).then(encryptedPlain=>{
            return GlobalCrypto.AES_SIV_N96_128_256_decrypt(encryptedPlain, key).then(decryptedPlain=>{
                expect(base64.stringify(plain) == base64.stringify(decryptedPlain)).toBeTrue();
                done();
            });
        });
    });*/

    it("check the Curve25519_ECDH shared secret", (done)=>{

        let keyPairA = nacl.box.keyPair();
        let keyPairB = nacl.box.keyPair();

        let shared1 = GlobalCrypto.Curve25519_ECDH(keyPairB.publicKey, keyPairA.secretKey);
        let shared2 = GlobalCrypto.Curve25519_ECDH(keyPairA.publicKey, keyPairB.secretKey);

        expect(base64.stringify(shared1) == base64.stringify(shared2)).toBeTrue();
        done();
    });

    it("check the Ed25519_256 sign/verify", (done)=>{

        let plain = crypto.getRandomValues(new Uint8Array(512));
        let keyPair = nacl.sign.keyPair();

        let signature = GlobalCrypto.Ed25519_256_sign(plain, keyPair.secretKey);

        expect(GlobalCrypto.Ed25519_256_verify(plain, signature, keyPair.publicKey)).toBeTrue();
        done();
    });

    it("check the HKDF_SHA256_256 generation", (done)=>{

        let rawKey = crypto.getRandomValues(new Uint8Array(32));
        let salt =  crypto.getRandomValues(new Uint8Array(8));

        GlobalCrypto.HKDF_SHA256_256(rawKey, salt).then((deriveBits)=>{
            expect(deriveBits).toBeTruthy();
            done();
        });

        
    });

    /*it("check the RSA_OAEP_SHA256 encrypt/decrypt", (done)=>{

        let plain = crypto.getRandomValues(new Uint8Array(128));
        
        // generate the key
        crypto.subtle.generateKey({
            name: "RSA-OAEP",
            modulusLength: 2048,
            hash: "SHA-256",
            publicExponent: new Uint8Array([1,0,1])
        }, true, ["encrypt", "decrypt"]).then((key)=>{

            // export a compatible format
            crypto.subtle.exportKey("pkcs8", key.privateKey).then((pem)=>{
                
                // generate key for keyutil from the compatible format
                let pemString = base64.stringify(new Uint8Array(pem));
                let pemFull = `-----BEGIN PRIVATE KEY-----\n`+pemString+`\n-----END PRIVATE KEY-----`;
                
                let keyObj = new keyutil.Key('pem', pemFull);
                keyObj.export('der', {outputPublic: true}).then((publicKey)=>{
                    keyObj.export('der').then((privateKey)=>{
                        GlobalCrypto.RSA_OAEP_SHA256_encrypt(plain, publicKey).then((encryptedPlain)=>{
                            
                            GlobalCrypto.RSA_OAEP_SHA256_decrypt(encryptedPlain, privateKey).then((decryptedPlain)=>{
                                
                                expect(base64.stringify(plain) == base64.stringify(decryptedPlain)).toBeTrue();
                                done();
        
                            });
                        });
                    });
                });
            });
        });


        
    });*/

    it("check the PBKDF2", (done)=>{
        
        let password = "password";
        let salt = "salt";
        let enc = new TextEncoder();

        GlobalCrypto.PBKDF2(enc.encode(password), enc.encode(salt)).then((key)=>{
            expect(key.byteLength == 64).toBeTrue();
            done();
        })
    });


});