
package de.ivu.elect.was.exchange.wahl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import javax.inject.Inject;

import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.SystemGruppe;
import de.ivu.elect.business.gruppeimgebiet.boundary.GruppeImGebietFactory;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.sitzberechnung.control.OsvSitzberechnungsalgorithmusFinder;
import de.ivu.elect.business.system.control.ElectDemoSystem;
import de.ivu.elect.business.wahl.control.NlWasWahlPostCreate;
import de.ivu.elect.business.wahl.entity.NlWahlart;
import de.ivu.elect.business.wahl.entity.WahlImportContext;
import de.ivu.elect.business.wahl.entity.WahlParameter;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.jee.exchange.Violations;
import de.ivu.elect.jee.faces.DevelopmentStore;
import de.ivu.elect.nl.eml.EmlWrapper;
import de.ivu.elect.presentation.NlSystemProperties;
import de.ivu.elect.presentation.NlWasSystemProperties;

public class WasEml110WahlImportMapper extends AbstractEml110WahlImportMapper<Wahldurchfuehrung, Wahldurchfuehrungsgebiet> implements WasWahlImportMapper {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient GruppeImGebietFactory gruppeImGebietFactory;

  @Inject
  private transient NlWasWahlPostCreate nlWasWahlPostCreate;

  @Inject
  private transient OsvSitzberechnungsalgorithmusFinder osvSitzberechnungsalgorithmusFinder;

  @Inject
  private transient NlSystemProperties nlSystemProperties;

  @Inject
  private transient NlWasSystemProperties nlWasSystemProperties;

  public WasEml110WahlImportMapper() {
    super();
  }

  @Override
  protected boolean isAlsWahldefinitionImportierenMoeglich() {
    return false; // Wahldefinition erfolgt in WUS
  }

  @Override
  protected void postWahlMapping(Wahldurchfuehrung wahl, EmlWrapper emlWrapper) {
    // erstmal setzen
    wahl.setSitzberechnungsalgorithmus(osvSitzberechnungsalgorithmusFinder.findeFuerWahlart(eml110Mapper.getElectionSubcategory(emlWrapper).name()));
  }

  @Override // ELECT-9761
  protected List<Gruppe> mappeGruppen(WahlImportContext context, EmlWrapper emlWrapper, Wahldurchfuehrung wahl, List<WahlParameter> wahlparameter) {
    List<Gruppe> gruppenAusDatei = Collections.emptyList();
    // ELECT-9943 List<Gruppe> gruppenAusDatei = super.mappeGruppen(context, emlWrapper, wahl, wahlparameter);

    List<Gruppe> result = new ArrayList<>(gruppenAusDatei);

    if (!nlWasWahlPostCreate.isCreateSystemgruppen()) {
      for (var systemGruppe : SystemGruppe.values()) {
        result.add(systemGruppeEigenschaften.createGruppeAusSystemGruppe(systemGruppe, wahl));
      }
    }

    return result;
  }

  @Override // ELECT-9761
  protected List<GruppeImGebiet> mappeGruppenImGebiet(List<Gebiet> gebiete, List<Gruppe> gruppen) {
    List<GruppeImGebiet> result = new ArrayList<>(super.mappeGruppenImGebiet(gebiete, gruppen));

    for (var gebiet : gebiete) {
      for (var gruppe : gruppen) {
        if (gruppe.isSystemGruppe()) {
          var gruppeImGebiet = gruppeImGebietFactory.create();
          gruppeImGebiet.setGruppe(gruppe);
          gruppeImGebiet.setGebiet(gebiet);

          result.add(gruppeImGebiet);
        }
      }
    }

    return result;
  }

  @Override
  protected void validiereWahlartUndDatum(EmlWrapper emlWrapper, Violations violations, WahlImportContext context) {
    // ELECT-15715
    var defaultWahldatum = nlSystemProperties.getDefaultWahldatum(context.getMandant());
    var wahldatumInDatei = eml110Mapper.extractDate(emlWrapper);
    if (defaultWahldatum.isPresent() && wahldatumInDatei != null) {
      if ((!Objects.equals(defaultWahldatum.get(), wahldatumInDatei))) {
        if (DevelopmentStore.isDevelopmentStage() || ElectDemoSystem.isDemoSystem()) {
          violations.addWarning("eml.110a.datum.passt.nicht");
        } else {
          violations.addError("eml.110a.datum.passt.nicht");
          return;
        }
      }
    } else {
      violations.addWarning("eml.110a.datum.kann.nicht.validiert.werden");
    }

    var defaultWahlart = nlWasSystemProperties.getDefaultWahlart(context.getMandant());
    var electionCategoryTypeInDatei = eml110Mapper.getElectionCategoryType(emlWrapper);
    if (defaultWahlart.isPresent() && electionCategoryTypeInDatei != null) {
      if ((!Objects.equals(defaultWahlart.get().name(), electionCategoryTypeInDatei.name()))) {
        if (DevelopmentStore.isDevelopmentStage() || ElectDemoSystem.isDemoSystem()) {
          violations.addWarning("eml.110a.wahlart.passt.nicht");
        } else {
          violations.addError("eml.110a.wahlart.passt.nicht");
        }
      }
    } else {
      violations.addWarning("eml.110a.wahlart.kann.nicht.validiert.werden");
    }

  }

  @Override
  public boolean isAcceptContext(WahlImportContext context) {
    return super.isAcceptContext(context) && (!isWahlVorhanden(context.getMandant())/*ELECT-9791*/ || isMehrereWahlenUnterstuetzt(context)/*ELECT-13397*/);
  }

  private boolean isMehrereWahlenUnterstuetzt(WahlImportContext context) {
    if (context.getMandant() == null) {
      return false;
    }

    var defaultElectionLevel = nlSystemProperties.getDefaultElectionLevel(context.getMandant());

    if (nlSystemProperties.getDefaultElectionLevel(context.getMandant()).isHSBC()) {
      return true; // ELECT-15712
    }

//    if (defaultElectionLevel.isReinesHsb() /*ELECT-15712*/) {
//      return true;
//    }

    // ELECT-13397 nur wenn PSB...
    if (!defaultElectionLevel.isPSB()) {
      return false;
    }

    // ELECT-13397 ...und bereits eine AB-Wahl vorhanden
    return isABWahlVorhanden(context.getMandant());

  }

  private boolean isABWahlVorhanden(Mandant mandant) {
    return wahlDAO.findByAll(mandant).stream().anyMatch(NlWahlart.WATERSCHAP::equalsWahlart);
  }

  private boolean isWahlVorhanden(Mandant mandant) {
    return !wahlDAO.findByAll(mandant).isEmpty();
  }
}
