
package de.ivu.elect.business.gebietsbaum.boundary;

import java.util.Collection;
import java.util.List;

import javax.annotation.Nullable;
import javax.ejb.Stateless;
import javax.inject.Inject;

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

import de.ivu.elect.business.gebietsbaum.entity.Gebietsart;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsarteigenschaft;
import de.ivu.elect.business.mandant.boundary.MandantDAO;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.wahl.boundary.WahlartCreateTemplate;
import de.ivu.elect.business.wahl.boundary.WahlartCreator;
import de.ivu.elect.business.wahl.control.WahlkonfigurationInitialerImport;
import de.ivu.elect.business.wahl.entity.Wahlart;

@Stateless
public class DefaultGebietsarteigenschaftCreator {

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

  @Inject
  protected transient WahlartCreator wahlartCreator;

  @Inject
  protected transient GebietsartCreator gebietsartCreator;

  @Inject
  protected transient GebietsarteigenschaftDAO gebietsarteigenschaftDao;

  @Inject
  private transient MandantDAO mandantDAO;

  @Inject
  private transient WahlkonfigurationInitialerImport wahlkonfigurationInitialerImport;

  public DefaultGebietsarteigenschaftCreator() {
    super();
  }

  public void initGebietsartenGebietsarteigenschaftenAlleMandanten() {
    for (Mandant mandant : mandantDAO.findByAll()) {
      if (mandant.getArt().isCustomerMandant()) {
        initGebietsartenGebietsarteigenschaften(mandant);
      }
    }
  }

  public void initGebietsartenGebietsarteigenschaften(Mandant mandant) {
    if (mandant.getArt().isCustomerMandant()) {
      LOG.info("Initialisiere Gebietsarteigenschaften für Mandant: " + mandant.getNummer());
      Collection<? extends WahlartCreateTemplate> wahlartTemplates = wahlartCreator.getWahlartCreateTemplates();
      if (wahlartTemplates.isEmpty()) {
        // ELECTKOM-174
        wahlkonfigurationInitialerImport.importiereWahlkonfigurationWennVorhanden(mandant);
      } else {
        legacyImport(mandant, wahlartTemplates);
      }
    }
  }

  // Für Systeme, die keine manuelle Anpassung ermöglichen
  protected void legacyImport(Mandant mandant, Collection<? extends WahlartCreateTemplate> wahlartTemplates) {
    Collection<? extends GebietsartTemplate> gebietsartTemplates = gebietsartCreator.getAnzulegendeGebietsartTemplates();

    List<Gebietsarteigenschaft> gebietsarteigenschaften = gebietsarteigenschaftDao.findByAll(mandant);

    for (WahlartCreateTemplate customWahlartTemplate : wahlartTemplates) {
      Wahlart wahlart = wahlartCreator.getWahlart(mandant, customWahlartTemplate);

      for (GebietsartTemplate customGebietsartTemplate : gebietsartTemplates) {
        if (!isKombinationGueltig(customWahlartTemplate, customGebietsartTemplate)) {
          continue;
        }

        GebietsarteigenschaftTemplate gebietsarteigenschaftTemplate = getGebietsarteigenschaftTemplate(customWahlartTemplate, customGebietsartTemplate);
        Gebietsart gebietsart = gebietsartCreator.getGebietsart(mandant, customGebietsartTemplate);
        Gebietsarteigenschaft vorhandeneGebietsarteigenschaft = findeGebietsarteigenschaft(wahlart, gebietsart, gebietsarteigenschaften);
        if (gebietsarteigenschaftTemplate == null) {
          if (vorhandeneGebietsarteigenschaft != null) {
            LOG.warn("Kombination nicht mehr gültig: " + vorhandeneGebietsarteigenschaft);
          }
        } else {
          // nur, wenn Kombination sinnvoll...
          if (vorhandeneGebietsarteigenschaft == null) { // Nur, wenn noch nicht in DB vorhanden
            createGebietsarteigenschaft(wahlart, gebietsart, gebietsarteigenschaftTemplate);
          } else {
            aktualisiereGebietsarteigenschaft(vorhandeneGebietsarteigenschaft, gebietsarteigenschaftTemplate);
          }
        }
      }
    }
  }

  private void aktualisiereGebietsarteigenschaft(Gebietsarteigenschaft vorhandeneGebietsarteigenschaft, GebietsarteigenschaftTemplate gebietsarteigenschaftTemplate) {
    // ELECT-8350
    gebietsarteigenschaftTemplate.fillGebietsarteigenschaft(vorhandeneGebietsarteigenschaft);
    if (vorhandeneGebietsarteigenschaft.isAttributeChanged()) {
      LOG.info("Bestehende Gebietsarteigenschaft aktualisiert: " + vorhandeneGebietsarteigenschaft);
    } else {
      LOG.info("Bestehende Gebietsarteigenschaft unverändert: " + vorhandeneGebietsarteigenschaft);
    }
  }

  protected boolean isKombinationGueltig(WahlartCreateTemplate customWahlartTemplate, GebietsartTemplate customGebietsartTemplate) {
    return customWahlartTemplate.isGueltigeWahlart(customGebietsartTemplate);
  }

  protected Gebietsarteigenschaft createGebietsarteigenschaft(Wahlart wahlart, Gebietsart gebietsart, GebietsarteigenschaftTemplate gebietsarteigenschaftTemplate) {
    Gebietsarteigenschaft gebietsarteigenschaft = new Gebietsarteigenschaft();

    gebietsarteigenschaft.setWahlart(wahlart);
    gebietsarteigenschaft.setGebietsart(gebietsart);

    gebietsarteigenschaftTemplate.fillGebietsarteigenschaft(gebietsarteigenschaft);

    gebietsarteigenschaftDao.persist(gebietsarteigenschaft);

    LOG.info("Gebietsarteigenschaft '" + wahlart + "', '" + gebietsart + "' angelegt");

    return gebietsarteigenschaft;
  }

  @Nullable
  private Gebietsarteigenschaft findeGebietsarteigenschaft(Wahlart wahlart, Gebietsart gebietsart, List<Gebietsarteigenschaft> gebietsarteigenschaften) {

    for (Gebietsarteigenschaft gebietsarteigenschaft : gebietsarteigenschaften) {
      if (wahlart.equals(gebietsarteigenschaft.getWahlart()) && gebietsart.equals(gebietsarteigenschaft.getGebietsart())) {
        return gebietsarteigenschaft;
      }
    }

    return null;
  }

  protected GebietsarteigenschaftTemplate getGebietsarteigenschaftTemplate(WahlartCreateTemplate customWahlartTemplate, GebietsartTemplate customGebietsartTemplate) {
    boolean wahlgebiet = customWahlartTemplate.isWahlgebietFor(customGebietsartTemplate);
    boolean direktwahlgebiet = customWahlartTemplate.isDirektwahlgebietFor(customGebietsartTemplate);
    boolean listenwahlgebiet = customWahlartTemplate.isListenwahlgebietFor(customGebietsartTemplate);
    boolean referendumgebiet = customWahlartTemplate.isReferendumgebietFor(customGebietsartTemplate);
    boolean listenkandidatenWaehlbar = customWahlartTemplate.isListenkandidatenWaehlbarFor(customGebietsartTemplate);
    boolean gruppenvereinigungenErlaubt = customWahlartTemplate.isGruppenvereinigungenErlaubt();
    boolean ergebnisRelevant = customWahlartTemplate.isErgebnisRelevantFor(customGebietsartTemplate);
    boolean erfassungsgebiet = customWahlartTemplate.isErfassungsgebietFor(customGebietsartTemplate);
    boolean briefwahlgebiet = customGebietsartTemplate.isBriefwahlbezirk();

    return new SimpleGebietsarteigenschaftTemplate(wahlgebiet, direktwahlgebiet, listenwahlgebiet, referendumgebiet, listenkandidatenWaehlbar,
            gruppenvereinigungenErlaubt, ergebnisRelevant,
            erfassungsgebiet, briefwahlgebiet);
  }

}
