package security;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import api.wsit.product_request.execute.ApiSchema;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;

import java.io.*;
import java.security.*;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class KeyUtility {
    static {
        if (Security.getProvider("BC") == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }
    public static List<PGPPublicKey> getPublicKeys(String fileName) {
        System.out.println("  #a. Retrieving Keys from: " + fileName);
        List<PGPPublicKey> pgpPublicKeys = new ArrayList<PGPPublicKey>();
        try {
            InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
            InputStream decoderStream = PGPUtil.getDecoderStream(inputStream);
            PGPPublicKeyRingCollection ringCollection = new PGPPublicKeyRingCollection(decoderStream, new JcaKeyFingerprintCalculator());
            PGPPublicKey pgpPublicKey = null;
            System.out.println("  #b. IDs of keys retrieved: ");
            for (PGPPublicKeyRing ring : ringCollection) {
                for (Iterator<PGPPublicKey> it = ring.getPublicKeys(); it.hasNext(); ) {
                    pgpPublicKey = it.next();
                    System.out.println("      " + Long.toHexString(pgpPublicKey.getKeyID()).toUpperCase());
                    pgpPublicKeys.add(pgpPublicKey);
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (PGPException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pgpPublicKeys;
    }

    public static PGPPublicKey getEncryptionKey(String apiSchema, List<PGPPublicKey> pgpPublicKeys) {
        PGPPublicKey pgpPublicKey = null;
        switch (apiSchema) {
            case (ApiSchema.Edge.SCHEMA_NAME):
                pgpPublicKey = pgpPublicKeys.get(0);
                break;
            case (ApiSchema.Gtrf.SCHEMA_NAME):
                for (Iterator<PGPPublicKey> it = pgpPublicKeys.iterator(); it.hasNext(); ) {
                    pgpPublicKey = it.next();
                    if (pgpPublicKey.isEncryptionKey() && !pgpPublicKey.isMasterKey()) {
                        break;
                    }
                }
        }
        System.out.println("  #a. ID of encryption key:\n      " + Long.toHexString(pgpPublicKey.getKeyID()).toUpperCase());
        return pgpPublicKey;
    }

    public static List<PGPPrivateKey> getPrivateKeys(String fileName, String keyPassPhrase) {
        System.out.println("  #a. Retrieving Keys from: " + fileName);
        List<PGPPrivateKey> pgpPrivateKeys = new ArrayList<PGPPrivateKey>();
        try {
            InputStream inputStream = new BufferedInputStream(new FileInputStream(fileName));
            InputStream decoderStream = PGPUtil.getDecoderStream(inputStream);
            PGPSecretKeyRingCollection ringCollection = new PGPSecretKeyRingCollection(decoderStream, new JcaKeyFingerprintCalculator());
            PGPSecretKey pgpSecretKey = null;
            PGPPrivateKey pgpPrivateKey = null;
            System.out.println("  #b. IDs of keys retrieved: ");
            for (PGPSecretKeyRing ring : ringCollection) {
                for (Iterator<PGPSecretKey> it = ring.getSecretKeys(); it.hasNext(); ) {
                    pgpSecretKey = it.next();
                    pgpPrivateKey = pgpSecretKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().build(keyPassPhrase.toCharArray()));
                    System.out.println("      " + Long.toHexString(pgpPrivateKey.getKeyID()).toUpperCase());
                    pgpPrivateKeys.add(pgpPrivateKey);
                }
            }
            return pgpPrivateKeys;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (PGPException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pgpPrivateKeys;
    }

}
