package de.tu_dresden.diplom.richter_mirko_mat2628335.common.keystore;

import org.apache.log4j.Logger;

import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.PrivateKey;
import java.security.KeyPair;
import java.io.File;

import de.tu_dresden.diplom.richter_mirko_mat2628335.Configuration;

/**
 * An application-specific abstraction layer over the keystore. Knows all
 * used entities for the prototyps (alias, passwd) and password of the keystore.
 */
public class ApplicationSpecificKeystoreUtility {

   private static final Logger logger = Logger.getLogger(ApplicationSpecificKeystoreUtility.class);

   //public static final String ENTITY_WITNESS = "witness";
   //public static final String ENTITY_CLIENT1 = "client1";

   private static final Configuration conf = new Configuration(Configuration.APPLICATION_BASE);

   /**
    * Location of the keystore-file (absolute path or relative to execution dir)
    */
   public static final String DEFAULT_KEYSTORE_LOCATION = conf.getKeystoreLocation();

   /**
    * Default password for the underlying keystore
    */
   public static final String DEFAULT_KEYSTORE_PASSWD = "acprototyp";

   /**
    * References the Entity "Witness".
    */
   public static final int ENTITY_WITNESS = 0;

   /**
    * References the Entity "Client1".
    */
   public static final int ENTITY_CLIENT1 = 1;

   /**
    * References the Entity "TicketReservation".
    */
   public static final int ENTITY_TICKET_RESERVATION = 2;

   /**
    * References the Entity "TicketBooking".
    */
   public static final int ENTITY_TICKET_BOOKING = 3;

   /**
    * References the Entity "Admin".
    */
   public static final int ENTITY_ADMIN = 4;

   /**
    * References the Entity "CertificateAuthority".
    */
   public static final int ENTITY_CA = 5;

   /**
    * References the Entity "TicketService".
    */
   public static final int ENTITY_TICKET_SERVICE = 6;

   /**
    * References the Entity "WitnessDigester".
    */
   public static final int ENTITY_WITNESS_DIGESTER = 7;

   /**
    * References the Entity "WitnessContextRegistrator".
    */
   public static final int ENTITY_WITNESS_CONTEXT_REGISTRATOR = 8;


   /**
    * Keystore-type for the Entity (position identified by the int ENTITY_${NAME})
    */
   public static final String[] KEYSTORE_TYPES = new String[]{"JCEKS",
                                                              "JCEKS",
                                                              "JCEKS",
                                                              "JCEKS",
                                                              "JCEKS",
                                                              "JCEKS",
                                                              "JCEKS",
                                                              "JCEKS",
                                                              "JCEKS"};

   /**
    * Keystore-location for the Entity (position identified by the int ENTITY_${NAME})
    */
   public static final String[] KEYSTORE_LOCATIONS = new String[]{DEFAULT_KEYSTORE_LOCATION,
                                                                  DEFAULT_KEYSTORE_LOCATION,
                                                                  DEFAULT_KEYSTORE_LOCATION,
                                                                  DEFAULT_KEYSTORE_LOCATION,
                                                                  DEFAULT_KEYSTORE_LOCATION,
                                                                  DEFAULT_KEYSTORE_LOCATION,
                                                                  DEFAULT_KEYSTORE_LOCATION,
                                                                  DEFAULT_KEYSTORE_LOCATION,
                                                                  DEFAULT_KEYSTORE_LOCATION};

   /**
    * Keystore-password for the Entity (position identified by the int ENTITY_${NAME})
    */
   public static final String[] KEYSTORE_PASSWDS = new String[]{DEFAULT_KEYSTORE_PASSWD,
                                                                DEFAULT_KEYSTORE_PASSWD,
                                                                DEFAULT_KEYSTORE_PASSWD,
                                                                DEFAULT_KEYSTORE_PASSWD,
                                                                DEFAULT_KEYSTORE_PASSWD,
                                                                DEFAULT_KEYSTORE_PASSWD,
                                                                DEFAULT_KEYSTORE_PASSWD,
                                                                DEFAULT_KEYSTORE_PASSWD,
                                                                DEFAULT_KEYSTORE_PASSWD};

   /**
    * ALIAS to obtain Signature key (DSA) (position identified by the int ENTITY_${NAME})
    */
   public static final String[] SIG_ALIASES = new String[]{"Witness",
                                                       "Client1",
                                                       "TicketReservation",
                                                       "TicketBooking",
                                                       "Admin",
                                                       "CA",
                                                       "TicketService",
                                                       "WitnessDigester",
                                                       "WitnessContextRegistrator"};


   /**
    * ALIAS to obtain Encryption key (RSA) (position identified by the int ENTITY_${NAME})
    */
   public static final String[] ENC_ALIASES = new String[]{"WitnessEnc",
                                                       "Client1Enc",
                                                       "TicketReservationEnc",
                                                       "TicketBookingEnc",
                                                       "AdminEnc",
                                                       "CAEnc",
                                                       "TicketServiceEnc",
                                                       "WitnessDigesterEnc",
                                                       "WitnessContextRegistratorEnc"};

   /**
    * Password to obtain private Signature key (DSA) (position identified by the int ENTITY_${NAME})
    */
   public static final String[] SIG_PASSWDS = new String[]{"ACPWitness",
                                                       "ACPClient1",
                                                       "ACPTicketReservation",
                                                       "ACPTicketBooking",
                                                       "ACPAdmin",
                                                       "ACPCertAuth",
                                                       "ACPTicketService",
                                                       "ACPWitnessDigester",
                                                       "ACPWitnessContextRegistrator"};

   /**
    * Password to obtain private Encryption key (DSA) (position identified by the int ENTITY_${NAME})
    */
   public static final String[] ENC_PASSWDS = new String[]{"ACPWitnessEnc",
                                                       "ACPClient1Enc",
                                                       "ACPTicketReservationEnc",
                                                       "ACPTicketBookingEnc",
                                                       "ACPAdminEnc",
                                                       "ACPCertAuthEnc",
                                                       "ACPTicketServiceEnc",
                                                       "ACPWitnessDigesterEnc",
                                                       "ACPWitnessContextRegistratorEnc"};

   /**
    * Mappings that are used to reference the private key for signature-testing
    * (position identified by the int ENTITY_${NAME})
    */
   public static final String[] SIG_KEYNAMES = new String[]{"The signature-cert of the Witness",
                                                        "The signature-cert of the Client 1",
                                                        "The signature-cert of the TicketReservation",
                                                        "The signature-cert of the TicketBooking",
                                                        "The signature-cert of the Admin",
                                                        "The signature-cert of the CA",
                                                        "The signature-cert of the TicketService",
                                                        "The signature-cert of the WitnessDigester",
                                                        "The signature-cert of the WitnessContextRegistrator"};

   /**
    * Mappings that are used to reference the private key for decryption
    * (position identified by the int ENTITY_${NAME})
    */
   public static final String[] ENC_KEYNAMES = new String[]{"The encryption-cert of the Witness",
                                                        "The encryption-cert of the Client 1",
                                                        "The encryption-cert of the TicketReservation",
                                                        "The encryption-cert of the TicketBooking",
                                                        "The encryption-cert of the Admin",
                                                        "The encryption-cert of the CA",
                                                        "The encryption-cert of the TicketService",
                                                        "The encryption-cert of the WitnessDigester",
                                                        "The encryption-cert of the WitnessContextRegistrator"};

   /**
    * Obtains signature-certificate of the entity identified by ist application specific ID.
    * @param entity The ID.
    * @return The Certificate to check the signature.
    */
   public static Certificate getCertificate4Signature(int entity) {
      final String fn = "[getCertificate4Signature]";
      if (logger.isDebugEnabled()) logger.debug(fn + " obtain signature-certificate for entity '" + entity + "' ...");
      Certificate result = null;
      result = KeystoreUtility.getCertificate(KEYSTORE_TYPES[entity], new File(KEYSTORE_LOCATIONS[entity]), KEYSTORE_PASSWDS[entity].toCharArray(), SIG_ALIASES[entity]);
      //if (logger.isDebugEnabled()) logger.debug(fn + " ... -> '" + result + "'");
      return result;
   }

   /**
    * Obtains encryption-certificate of the entity identified by ist application specific ID.
    * @param entity The ID.
    * @return The Certificate to encrypt some content.
    */
   public static Certificate getCertificate4Encryption(int entity) {
      final String fn = "[getCertificate4Encryption] ";
      if (logger.isDebugEnabled()) logger.debug(fn + " obtain encryption-certificate for entity '" + entity + "' ...");
      Certificate result = null;
      result = KeystoreUtility.getCertificate(KEYSTORE_TYPES[entity], new File(KEYSTORE_LOCATIONS[entity]), KEYSTORE_PASSWDS[entity].toCharArray(), ENC_ALIASES[entity]);
      //if (logger.isDebugEnabled()) logger.debug(fn + " ... -> '" + result + "'");
      return result;
   }

   /**
    * Obtains certificate as X509-cert.
    * @see ApplicationSpecificKeystoreUtility#getCertificate4Signature(int)
    */
   public static X509Certificate getX509Certificate4Signature(int entity) {
      return (X509Certificate) getCertificate4Signature(entity);
   }

   /**
    * Obtains the private key for signature-creation of the entity identified by the ID.
    * @param entity The ID.
    * @return The Private Key.
    */
   public static PrivateKey getPrivateKey4Signature(int entity) {
      PrivateKey result = null;
      result = KeystoreUtility.getPrivateKey(KEYSTORE_TYPES[entity], new File(KEYSTORE_LOCATIONS[entity]), KEYSTORE_PASSWDS[entity].toCharArray(), SIG_ALIASES[entity], SIG_PASSWDS[entity].toCharArray());
      return result;
   }

   /**
    * Obtains the private and public key of the entity identified by the ID.
    * @param entity The ID.
    * @return The Key Pair.
    */
   public static KeyPair getKeyPair4Signature(int entity) {
      KeyPair result = null;
      result = KeystoreUtility.getKeyPair(KEYSTORE_TYPES[entity], new File(KEYSTORE_LOCATIONS[entity]), KEYSTORE_PASSWDS[entity].toCharArray(), SIG_ALIASES[entity], SIG_PASSWDS[entity].toCharArray());
      return result;
   }

   /**
    * Resolves the given keyName to the apllication specific, unique entity ID.
    * @param keyName The name of the entity.
    * @return The ID of the Entity.
    */
   public static int getEntityIDByKeyname(String keyName) {
      int result = -1;
      for (int i = 0; i < SIG_KEYNAMES.length; i++) {
         String currKeyname = SIG_KEYNAMES[i];
         if (currKeyname.equals(keyName)) {
            result = i;
            break;
         }
      }
      return result;
   }

   /**
    * Resolves the given alias to the apllication specific, unique entity ID.
    * @param alias The Alias of the Entity to resolve.
    * @return The ID of the Entity.
    */
   public static int getEntityIDByAlias(String alias) {
      int result = -1;
      for (int i = 0; i < SIG_ALIASES.length; i++) {
         String currAlias = SIG_ALIASES[i];
         if (currAlias.equals(alias)) {
            result = i;
            break;
         }
      }
      return result;
   }

   /**
    * Resolves the given unique application specific entity ID to the name of the entity.
    * @param id The ID to resolve
    * @return The name of the entity.
    */
   public static String getEntityNameByID(int id) {
      String result = null;
      if (id >= 0 && id < SIG_ALIASES.length) {
         result = SIG_ALIASES[id];
      }
      return result;
   }
}
