
package de.ivu.elect.presentation.security;

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

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.NoResultException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.gebietsbaum.boundary.GebietExtendedDAO;
import de.ivu.elect.business.gebietsbaum.boundary.GebietSessionSelect;
import de.ivu.elect.business.gebietsbaum.boundary.SecurityGebietSessionSelect;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietPK;
import de.ivu.elect.business.konfiguration.entity.ElectKonfigurationWerte;
import de.ivu.elect.business.konfiguration.entity.KonfigurationLoader;
import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.business.wahl.boundary.WahlterminExtendedDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminSessionSelect;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.business.wahl.entity.WahlterminPK;
import de.ivu.elect.jee.faces.Escape;
import de.ivu.elect.jee.faces.FacesMessageUtil;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;

/**
 *  on 03.07.2015.
 */
@RequestScoped
@Named(ElectRedirectParameterEvaluation.COMPONENT_NAME)
public class ElectRedirectParameterEvaluation implements Serializable {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "electRedirectParameterEvaluation";

  private static final Logger LOGGER = LoggerFactory.getLogger(ElectRedirectParameterEvaluation.class);

  @Inject
  private transient GebietSessionSelect gebietSessionSelect;

  @Inject
  private transient GebietExtendedDAO gebietExtendedDAO;

  @Inject
  private transient SecurityGebietSessionSelect securityGebietSessionSelect;

  @Inject
  private transient WahlterminSessionSelect wahlterminSessionSelect;

  @Inject
  private transient WahlterminExtendedDAO wahlterminExtendedDAO;

  @Inject
  private transient ElectCommonPrincipal principal;

  @Inject
  private transient WahlterminZurBearbeitungAuswaehlen wahlterminZurBearbeitungAuswaehlen;

  @Inject
  private transient GebietNummerFormatter gebietNummerFormatter;

  @Inject
  private transient KonfigurationLoader konfigurationLoader;

  @Inject
  private transient Escape escape;

  public ElectRedirectParameterEvaluation() {
    super();
  }

  public boolean isWahlWechselMoeglich() {
    return false;
  }

  public boolean isWahlterminWechselMoeglich() {
    return true;
  }

  public boolean isGebietWechselMoeglich() {
    return true;
  }

  public void accept(Map<String, String> parameter) {
    if (principal.isLoggedIn() && konfigurationLoader.resolveBooleanValue(ElectKonfigurationWerte.DEEP_LINKING_ENABLED)) {
      if (isWahlterminWechselMoeglich() && parameter.containsKey(ElectRedirectParameterAttachement.ELECT_WAHLTERMIN_ID)) {
        setzWahlterminAusParameter(parameter);
      }

      if (isWahlWechselMoeglich() && parameter.containsKey(ElectRedirectParameterAttachement.ELECT_WAHL_ID)) {
        setzWahlAusParameter(parameter);
      }

      if (isGebietWechselMoeglich() && parameter.containsKey(ElectRedirectParameterAttachement.ELECT_GEBIET_ID)) {
        setzGebietAusParameter(parameter);
      }
    }
  }

  private void setzGebietAusParameter(Map<String, String> parameter) {
    try {
      String gebietIdAsString = parameter.get(ElectRedirectParameterAttachement.ELECT_GEBIET_ID);

      if (gebietIdAsString != null) {
        Long gebietId = null;

        try {
          gebietId = Long.parseLong(gebietIdAsString);
        } catch (NumberFormatException ignored) {
          logWarn("GebietId kann nicht geparst werden: ", gebietIdAsString);
        }

        if (gebietId != null) {
          if (!gebietSessionSelect.isSelected() || !gebietId.equals(gebietSessionSelect.getEntity().getId())) {
            Gebiet gebiet = null;

            try {
              gebiet = gebietExtendedDAO.findByPrimaryKey(new GebietPK(gebietId));
            } catch (NoResultException ignored) {
            }

            if (gebiet != null) {
              if (securityGebietSessionSelect.isSetzenErlaubt(gebiet)) {
                securityGebietSessionSelect.setEntity(gebiet);

                FacesMessageUtil.addInfoMessage("gebiet.selected", "gebiet.selected", gebietNummerFormatter.getDarstellung(gebiet));

                logInfo("Gebiet gesetzt: ", gebietIdAsString);
              } else {
                logWarn("Kein Recht für Gebiet: ", gebietIdAsString);
              }
            } else {
              logWarn("Gebiet nicht gefunden: ", gebietIdAsString);
            }
          }
        }
      }
    } catch (Exception ex) {
      logWarn("Fehler beim Setzten des Gebietes: " + ex.getMessage(), "", ex);
    }
  }


  private void setzWahlterminAusParameter(Map<String, String> parameter) {
    try {
      String wahlterminIdAsString = parameter.get(ElectRedirectParameterAttachement.ELECT_WAHLTERMIN_ID);

      if (wahlterminIdAsString != null) {
        Long wahlterminId = null;

        try {
          wahlterminId = Long.parseLong(wahlterminIdAsString);
        } catch (NumberFormatException ignored) {
          logWarn("WahlterminId kann nicht geparst werden: ", wahlterminIdAsString);
        }

        if (wahlterminId != null) {
          if (!wahlterminSessionSelect.isSelected() || !wahlterminId.equals(wahlterminSessionSelect.getEntity().getId())) {
            Wahltermin wahltermin = null;

            try {
              wahltermin = wahlterminExtendedDAO.findByPrimaryKey(new WahlterminPK(wahlterminId));
            } catch (NoResultException ignored) {
            }

            if (wahltermin != null) {
              if (wahlterminZurBearbeitungAuswaehlen.isActionPossible(wahltermin)) {
                wahlterminZurBearbeitungAuswaehlen.doIt(wahltermin);

                logInfo("Wahltermin gesetzt: ", wahlterminIdAsString);
              } else {
                logWarn("Kein Recht für Wahltermin: ", wahlterminIdAsString);
              }
            } else {
              logWarn("Wahltermin nicht gefunden: ", wahlterminIdAsString);
            }
          }
        }
      }
    } catch (Exception ex) {
      logWarn("Fehler beim Setzten des Wahltermins: " + ex.getMessage(), "", ex);
    }
  }

  protected void setzWahlAusParameter(Map<String, String> parameter) {
    // nichts zu tun
  }

  protected void logWarn(String message, String parameteterValue) {
    LOGGER.warn("Principal: " + principal.getLogin().getBenutzerkennung() + ", " + message + escape.encodeUrl(parameteterValue));
  }

  protected void logWarn(String message, String parameteterValue, Throwable ex) {
    LOGGER.warn("Principal: " + principal.getLogin().getBenutzerkennung() + ", " + message + escape.encodeUrl(parameteterValue), ex);
  }

  protected void logInfo(String message, String parameteterValue) {
    LOGGER.info("Principal: " + principal.getLogin().getBenutzerkennung() + ", " + message + escape.encodeUrl(parameteterValue));
  }

}
