package com.airlock.iam.security.certificate;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;

public final class KeyStoreBuilder {
   private final List<KeyStoreEntryBuilder<?>> entryBuilders = new ArrayList<>();
   private final String type;
   private String password = "password";

   public static KeyStoreBuilder pkcs12KeyStoreBuilder() {
      return new KeyStoreBuilder("PKCS12");
   }

   public static KeyStoreBuilder jksKeyStoreBuilder() {
      return new KeyStoreBuilder("JKS");
   }

   private KeyStoreBuilder(String type) {
      this.type = type;
   }

   public KeyStoreBuilder withPassword(String keyStorePassword) {
      this.password = keyStorePassword;
      return this;
   }

   public KeyStoreBuilder withEntry(KeyStoreEntryBuilder<?> entry) {
      this.entryBuilders.add(entry);
      return this;
   }

   public byte[] buildAsByteArray() {
      try {
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         KeyStore keystore = this.build();
         keystore.store(outputStream, this.password.toCharArray());
         return outputStream.toByteArray();
      } catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
         throw new IllegalStateException(e);
      }
   }

   public KeyStore build() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
      KeyStore keyStore = KeyStore.getInstance(this.type);
      keyStore.load(null, this.password.toCharArray());

      for (KeyStoreEntryBuilder<?> entry : this.entryBuilders) {
         entry.addTo(keyStore);
      }

      return keyStore;
   }

   public KeyStore buildAndSaveToFile(Path outputFile) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException {
      KeyStore keyStore = this.build();

      try (OutputStream out = Files.newOutputStream(outputFile)) {
         keyStore.store(out, this.password.toCharArray());
      }

      return keyStore;
   }
}
