
package de.ivu.elect.business.stimmeingabe.control.plausi;

import static de.ivu.elect.jee.protokollierung.AttributTyp.DOUBLE;
import static de.ivu.elect.jee.protokollierung.AttributTyp.ENUM;
import static de.ivu.elect.jee.protokollierung.AttributTyp.STRING;
import static java.util.Objects.nonNull;

import java.util.*;

import de.ivu.elect.business.gruppe.entity.GruppeTK;
import de.ivu.elect.business.stimmeingabe.entity.*;
import de.ivu.elect.jee.presentation.dynamicform.Property;
import de.ivu.elect.jee.presentation.dynamicform.SeparatorPseudoProperty;
import de.ivu.elect.presentation.stimmeingabe.form.GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomDataGruppeProperty;
import de.ivu.elect.presentation.stimmeingabe.form.GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomDataObererSchwellwertProperty;
import de.ivu.elect.presentation.stimmeingabe.form.GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomDataSchwellwertTypProperty;
import de.ivu.elect.presentation.stimmeingabe.form.GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomDataUntererSchwellwertProperty;

public class GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData
    extends
      AbstractStimmeingabePlausiKonfigurationCustomData {

  private static final long serialVersionUID = 1L;

  /**
   * ACHTUNG: Folgende Message-Properties sind von der Anzahl abhängig:
   * GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData.schwellwert.gruppe.*
   * GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData.schwellwert.unterer.*
   * GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData.schwellwert.oberer.*
   * GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData.schwellwert.typ.*
   */
  private static final int ANZAHL_GRUPPEN_MIT_SCHWELLWERT = 10;

  private List<GruppeStimmenAnteilComparedToVorperiodeSchwellwert> schwellwerte;

  public List<GruppeStimmenAnteilComparedToVorperiodeSchwellwert> getSchwellwerte() {
    if (schwellwerte == null) {
      schwellwerte = new ArrayList<>(ANZAHL_GRUPPEN_MIT_SCHWELLWERT);
    }
    if (schwellwerte.size() < ANZAHL_GRUPPEN_MIT_SCHWELLWERT) {
      for (long i = schwellwerte.size(); i < ANZAHL_GRUPPEN_MIT_SCHWELLWERT; i++) {
        schwellwerte.add(new GruppeStimmenAnteilComparedToVorperiodeSchwellwert(i));
      }
    }
    return schwellwerte;
  }

  public GruppeStimmenAnteilComparedToVorperiodeSchwellwert getSchwellwert(Long id) {
    if (id == null) {
      return null;
    }
    return getSchwellwerte().stream().filter(schwellwert -> id.equals(schwellwert.getId())).findFirst().orElse(null);
  }

  public GruppeStimmenAnteilComparedToVorperiodeSchwellwert getSchwellwert(GruppeTK gruppeTK) {
    if (gruppeTK == null) {
      return null;
    }
    return getSchwellwerte().stream().filter(schwellwert -> gruppeTK.equals(schwellwert.getGruppeTK())).findFirst()
        .orElse(null);
  }

  public void setGruppeTK(Long schwellwertId, GruppeTK gruppeTK) {
    GruppeStimmenAnteilComparedToVorperiodeSchwellwert schwellwert = getSchwellwert(schwellwertId);
    GruppeTK alterGruppeTK = schwellwert.getGruppeTK();
    schwellwert.setGruppeTK(gruppeTK);
    String oldValue = null;
    if (alterGruppeTK != null) {
      oldValue = alterGruppeTK.toString();
    }
    String newValue = null;
    if (gruppeTK != null) {
      newValue = gruppeTK.toString();
    }
    notifyEntity("GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData.schwellwert.gruppe."
        + schwellwertId, STRING, oldValue, newValue);
  }

  public void setUntererSchwellwert(Long schwellwertId, Double untererSchwellwert) {
    GruppeStimmenAnteilComparedToVorperiodeSchwellwert schwellwert = getSchwellwert(schwellwertId);
    Double alterUntererSchwellwert = schwellwert.getUntererSchwellwert();
    schwellwert.setUntererSchwellwert(untererSchwellwert);
    notifyEntity("GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData.schwellwert.unterer."
        + schwellwertId, DOUBLE, alterUntererSchwellwert, untererSchwellwert);
  }

  public void setObererSchwellwert(Long schwellwertId, Double obererSchwellwert) {
    GruppeStimmenAnteilComparedToVorperiodeSchwellwert schwellwert = getSchwellwert(schwellwertId);
    Double alterObererSchwellwert = schwellwert.getObererSchwellwert();
    schwellwert.setObererSchwellwert(obererSchwellwert);
    notifyEntity("GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData.schwellwert.oberer."
        + schwellwertId, DOUBLE, alterObererSchwellwert, obererSchwellwert);
  }

  public void setSchwellwertTyp(Long schwellwertId, GruppeStimmenAnteilComparedToVorperiodeSchwellwertTyp schwellwertTyp) {
    GruppeStimmenAnteilComparedToVorperiodeSchwellwert schwellwert = getSchwellwert(schwellwertId);
    GruppeStimmenAnteilComparedToVorperiodeSchwellwertTyp alterSchwellwertTyp = schwellwert.getSchwellwertTyp();
    schwellwert.setSchwellwertTyp(schwellwertTyp);
    notifyEntity("GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData.schwellwert.typ."
        + schwellwertId, ENUM, alterSchwellwertTyp, schwellwertTyp);
  }

  @Override
  public Map<StimmeingabePlausiKonfigurationCustomDataKategorie, List<Object>> getParameters() {
    Map<StimmeingabePlausiKonfigurationCustomDataKategorie, List<Object>> result = new HashMap<>();

    result.put(StimmeingabePlausiKonfigurationCustomDataKategorie.KOMPLEXER_TYP, getSchwellWerteAsObjectList());

    return result;
  }

  private List<Object> getSchwellWerteAsObjectList() {
    return new ArrayList<>(getSchwellwerte());
  }

  @Override
  public Map<StimmeingabePlausiKonfigurationCustomDataKategorie, List<Property>> getProperties(
      StimmeingabePlausiKonfigurationPropertyContext context) {
    Map<StimmeingabePlausiKonfigurationCustomDataKategorie, List<Property>> result = new HashMap<>();
    List<Property> schwellwerteProperties = new ArrayList<>();
    addSchwellwerteProperties(schwellwerteProperties, context);
    result.put(StimmeingabePlausiKonfigurationCustomDataKategorie.KOMPLEXER_TYP, schwellwerteProperties);

    return result;
  }

  private void addSchwellwerteProperties(List<Property> schwellwerteProperties,
      StimmeingabePlausiKonfigurationPropertyContext context) {
    for (GruppeStimmenAnteilComparedToVorperiodeSchwellwert schwellwert : getSchwellwerte()) {
      Long schwellwertId = schwellwert.getId();
      schwellwerteProperties.add(new SeparatorPseudoProperty(""));
      schwellwerteProperties
          .add(new GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomDataGruppeProperty(this,
              schwellwertId, context));
      schwellwerteProperties
          .add(new GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomDataSchwellwertTypProperty(this,
              schwellwertId, context));
      schwellwerteProperties.add(
          new GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomDataUntererSchwellwertProperty(
              this, schwellwertId, context));
      schwellwerteProperties.add(
          new GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomDataObererSchwellwertProperty(
              this, schwellwertId, context));
    }
  }

  @Override
  public String formatFehlermeldungBeispiel(StimmeingabePlausiKonfiguration stimmeingabePlausiKonfiguration,
      StimmeingabePlausiFormatter stimmeingabePlausiFormatter) {
    Object abweichungZurVorperiode = "x";
    Object untererSchwellwert = "y";
    Object obererSchwellwert = "z";
    GruppeStimmenAnteilComparedToVorperiodeSchwellwertTyp schwellwertTyp = GruppeStimmenAnteilComparedToVorperiodeSchwellwertTyp.PROZENTPUNKTE;
    if (getSchwellwerte().size() > 0) {
      GruppeStimmenAnteilComparedToVorperiodeSchwellwert ersterSchwellwert = getSchwellwerte().get(0);
      if (ersterSchwellwert.getUntererSchwellwert() != null) {
        untererSchwellwert = ersterSchwellwert.getUntererSchwellwert();
      }
      if (ersterSchwellwert.getObererSchwellwert() != null) {
        obererSchwellwert = ersterSchwellwert.getObererSchwellwert();
      }
      schwellwertTyp = ersterSchwellwert.getSchwellwertTyp();
    }

    return stimmeingabePlausiFormatter.formatFehlermeldungBeispiel(stimmeingabePlausiKonfiguration.getWahl(),
        stimmeingabePlausiKonfiguration.getErgebniseingangsart(), stimmeingabePlausiKonfiguration.getTyp(),
        stimmeingabePlausiKonfiguration.getFehlerart(), null, null,
        untererSchwellwert, obererSchwellwert, schwellwertTyp.getId(), abweichungZurVorperiode);
  }

  @Override
  public boolean isCustomDataDefaultOverridden(StimmeingabePlausiKonfigurationCustomData customDataDefault) {
    if (customDataDefault instanceof GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData) {
      GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData defaultData = (GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData) customDataDefault;
      return !isAlleSchwellwerteInCustomData(getSchwellwerte(), defaultData)
          || !isAlleSchwellwerteInCustomData(defaultData.getSchwellwerte(), this);
    }
    return true;
  }

  private boolean isAlleSchwellwerteInCustomData(List<GruppeStimmenAnteilComparedToVorperiodeSchwellwert> schwellwerte,
      GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData customData) {
    for (GruppeStimmenAnteilComparedToVorperiodeSchwellwert schwellwert : schwellwerte) {
      if (nonNull(schwellwert.getUntererSchwellwert()) || nonNull(schwellwert.getObererSchwellwert())) {
        GruppeStimmenAnteilComparedToVorperiodeSchwellwert defaultSchwellwert = customData
            .getSchwellwert(schwellwert.getGruppeTK());
        if (defaultSchwellwert == null) {
          return false;
        }
        if (nonNull(defaultSchwellwert.getUntererSchwellwert())
            && !defaultSchwellwert.getUntererSchwellwert().equals(schwellwert.getUntererSchwellwert())
            || nonNull(defaultSchwellwert.getObererSchwellwert())
                && !defaultSchwellwert.getObererSchwellwert().equals(schwellwert.getObererSchwellwert())) {
          return false;
        }
      }
    }
    return true;
  }

  @Override
  public void resetToDefault(StimmeingabePlausiKonfigurationCustomData customDataDefault) {
    if (customDataDefault instanceof GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData) {
      GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData defaultData = (GruppeListenstimmenAnteilComparedToVorperiodeKleinerGleichSchwellwertCustomData) customDataDefault;
      schwellwerte = defaultData.getSchwellwerte();
    }
  }
}
