package de.ivu.elect.business.system.control;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.konfiguration.entity.ElectKonfigurationWerte;
import de.ivu.elect.business.konfiguration.entity.KonfigurationLoader;
import de.ivu.elect.jee.faces.HttpSecurityHeader;
import de.ivu.elect.presentation.security.LoginPhaseListener;


import static de.ivu.elect.business.system.control.HttpHeaderKonfigurationHelper.getHeaderKeyForParameter;
import static de.ivu.elect.business.system.control.HttpHeaderKonfigurationHelper.getHttpHeaderKonfigurationswerte;

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class HttpHeaderKonfigurationAktualisieren implements Serializable {

  private static final Logger LOG = LoggerFactory.getLogger(HttpHeaderKonfigurationAktualisieren.class);

  private static final long serialVersionUID = 1L;

  @Inject
  private transient KonfigurationLoader konfigurationLoader;

  public void aktualisiereHttpHeader() {
    LOG.info("Aktualisiere HTTP-Header");

    Map<String, String> newHeaderMap = new HashMap<>();

    for (ElectKonfigurationWerte electKonfigurationWerte : getHttpHeaderKonfigurationswerte()) {
      String value = konfigurationLoader.resolveStringValue(electKonfigurationWerte);

      if (ElectKonfigurationWerte.HTTP_HEADER_ADDITIONAL.equals(electKonfigurationWerte)) {
        addAdditionalParameters(newHeaderMap, value);
      } else {
        addParameter(newHeaderMap, electKonfigurationWerte, value);
      }
    }

    // ELECTKOM-369
    String dashBoardIframeHost = konfigurationLoader.resolveStringValue(ElectKonfigurationWerte.DASHBOARD_NEWS_IFRAME_HOST);
    if (StringUtils.isNotBlank(dashBoardIframeHost)) {
      addIframeContentSecurity(dashBoardIframeHost, newHeaderMap, ElectKonfigurationWerte.HTTP_HEADER_CONTENT_SECURITY_POLICY_OVERRIDE);
    }

    LOG.info("Neue HTTP-Header: " + newHeaderMap);
    HttpSecurityHeader.HEADER_MAP.clear();
    if (!HttpSecurityHeader.CSP_ENABLED.get()) {
      newHeaderMap.remove(HttpSecurityHeader.CONTENT_SECURITY_POLICY);
    }
    HttpSecurityHeader.HEADER_MAP.putAll(newHeaderMap);

    aktualisiereLoggingLogin();
    LOG.info("Aktualisiere HTTP-Header - done");

  }

  private void aktualisiereLoggingLogin() {
    boolean loggongActive = konfigurationLoader.resolveBooleanValue(ElectKonfigurationWerte.HTTP_LOGGING_LOGIN_ACCESS);
    LOG.info("LoggingLogin: " + loggongActive);
    LoginPhaseListener.LOGGE_ZUGRIFF_LOGIN_SEITE.set(loggongActive);
  }

  private void addIframeContentSecurity(String dashBoardIframeHost, Map<String, String> newHeaderMap, ElectKonfigurationWerte electKonfigurationWerte) {
    String alterWert = newHeaderMap.get(getHeaderKeyForParameter(electKonfigurationWerte));
    if (alterWert == null) {
      alterWert = "";
    }
    if (alterWert.toLowerCase().contains("frame-src")) {
      LOG.warn("frame-src bereits vorhanden - skip");
    }
    String neuerWert = alterWert;
    if (!neuerWert.endsWith(";")) {
      neuerWert += ";";
    }
    neuerWert += " frame-src 'self' " + dashBoardIframeHost; // self wegen ELECT-8932
    newHeaderMap.put(getHeaderKeyForParameter(electKonfigurationWerte), neuerWert);
  }

  private void addAdditionalParameters(Map<String, String> newHeaderMap, String additionalValue) {
    LOG.info("HTTP-Header - additional Parameters: " + additionalValue);
    if (StringUtils.isBlank(additionalValue)) {
      return;
    }

    String[] parameterPairs = additionalValue.split("§");
    for (String parameterPair : parameterPairs) {
      String[] keyValue = parameterPair.split("\\|");
      if (keyValue.length == 2) {
        String key = keyValue[0];
        String value = keyValue[1];
        if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(value)) {
          LOG.info("HTTP-Header - additional Parameter: key='" + key + "', value='" + value + "'");
          newHeaderMap.put(key, value);
        }
      }
    }
  }

  private void addParameter(Map<String, String> newHeaderMap, ElectKonfigurationWerte electKonfigurationWerte, String value) {
    LOG.info("HTTP-Header: electKonfigurationWerte = [" + electKonfigurationWerte + "], value = [" + value + "], default: "+ getDefaultValue(electKonfigurationWerte)+"]");
    if (StringUtils.isBlank(value)) {
      newHeaderMap.put(getHeaderKeyForParameter(electKonfigurationWerte), getDefaultValue(electKonfigurationWerte));
    } else {
      newHeaderMap.put(getHeaderKeyForParameter(electKonfigurationWerte), value);
    }
  }

  private String getDefaultValue(ElectKonfigurationWerte electKonfigurationWerte) {
    return (String) electKonfigurationWerte.getDefaults().getOrDefault(HttpSecurityHeader.class.getSimpleName(), "");
  }

}
