
package de.ivu.elect;

import java.security.PrivateKey;
import java.security.PublicKey;

import javax.annotation.Nullable;

import de.ivu.elect.business.exchange.control.AbstractExchangeContext;
import de.ivu.elect.business.exchange.control.ContextMitCustomParameter;
import de.ivu.elect.business.gebietsbaum.boundary.NlGebietDarstellungNummerFormatter;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.security.boundary.EmlSignKeyService;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.exception.ElectCommonException;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaBooleanProperty;
import de.ivu.elect.nl.eml.readable.ManagingAuthorityWrapper;
import de.ivu.elect.nl.x509.NlX509Metadata;

public interface EmlExportMapper {

  String EML_FILE_EXTENSION = ".eml.xml";

  String EML_SIGNATURE_FILE_EXTENSION = ".signature";

  String EML_HASHCODE_FILE_EXTENSION = ".hashcode.txt";

  String EML_SIGN_SKIP_KEY = "EML_SIGN_SKIP_KEY";

  boolean isSignEml(Wahl wahl);

  default @Nullable PrivateKey retrievePrivateKey(Wahl wahl, AbstractExchangeContext context, EmlSignKeyService emlSignKeyService) {
    if (!isSignEml(wahl) || Boolean.TRUE.equals(context.get(EML_SIGN_SKIP_KEY, Boolean.class))) {
      return null;
    }

    PrivateKey privateKey = emlSignKeyService.loadPrivateKey(wahl);

    if (privateKey == null) {
      throw new ElectCommonException("eml.export.private.key.not.found");
    }

    return privateKey;
  }

  default @Nullable PublicKey retrievePublicKey(Wahl wahl, AbstractExchangeContext context, EmlSignKeyService emlSignKeyService) {
    if (!isSignEml(wahl) || Boolean.TRUE.equals(context.get(EML_SIGN_SKIP_KEY, Boolean.class))) {
      return null;
    }

    PublicKey publicKey = emlSignKeyService.loadPublicKey(wahl);

    if (publicKey == null) {
      throw new ElectCommonException("eml.export.public.key.not.found");
    }

    return publicKey;
  }

  default @Nullable NlX509Metadata retrieveNlX509Metadata(Wahl wahl, AbstractExchangeContext context, EmlSignKeyService emlSignKeyService) {
    if (!isSignEml(wahl) || Boolean.TRUE.equals(context.get(EML_SIGN_SKIP_KEY, Boolean.class))) {
      return null;
    }

    NlX509Metadata nlX509Metadata = emlSignKeyService.getNlX509Metadata(wahl);

    if (nlX509Metadata == null) {
      throw new ElectCommonException("eml.export.x509.metadata.not.found");
    }

    return nlX509Metadata;
  }

  default void addSignProperties(Wahl wahl, FormBuilder formBuilder, ContextMitCustomParameter context, Messages messages) {
    // deaktiviert mit ELECTVAPP-1149
//    if (isSignEml(wahl)) {
//      formBuilder.addSeparator("eml.export.signatur.separator");
//
//      formBuilder.addProperty(
//          new LambdaBooleanProperty(messages.getMessageForMessageKey("eml.export.ohne.signieren"), false, b -> context.put(EML_SIGN_SKIP_KEY, b), () -> context.get(EML_SIGN_SKIP_KEY, Boolean.class)));
//    }
  }

  default void fillManagingAuthority(ManagingAuthorityWrapper managingAuthority, Gebiet gebietFuerDaten, Gebiet oberstesGebiet, NlGebietDarstellungNummerFormatter nlGebietDarstellungNummerFormatter,
      String authorityIdPrefix, String createdByAuthorityIdPrefix) {
    if (gebietFuerDaten != null) {
      if (authorityIdPrefix.contains("CSB")) {
        managingAuthority.setAuthorityName(authorityIdPrefix);
        managingAuthority.setAuthorityId("CSB"); // ELECTVAPP-1334 TODO für GR nochmal prüfen...
      } else {
        managingAuthority.setAuthorityId(authorityIdPrefix + nlGebietDarstellungNummerFormatter.formatiereNummer(gebietFuerDaten));
      }

      managingAuthority.setAuthorityName(gebietFuerDaten.getName());
    }

    if (!oberstesGebiet.equals(gebietFuerDaten)) {
      if (createdByAuthorityIdPrefix.contains("CSB")) {
        managingAuthority.setCreatedByAuthorityId(createdByAuthorityIdPrefix);
      } else {
        managingAuthority.setCreatedByAuthorityId(createdByAuthorityIdPrefix + nlGebietDarstellungNummerFormatter.formatiereNummer(oberstesGebiet));
      }

      managingAuthority.setCreatedByAuthorityName(oberstesGebiet.getName());
    }
  }
}
