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

import java.util.List;
import java.util.function.BiFunction;

import de.ivu.elect.business.auffaelligkeit.entity.AbstandartZwischenGebieten;
import de.ivu.elect.business.hochrechnung.entity.AbstandGetter;
import de.ivu.elect.business.hochrechnung.entity.GebietDaten;
import de.ivu.elect.business.hochrechnung.entity.KoordinatenInformationen;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaEnumProperty;


import static de.ivu.elect.business.hochrechnung.control.StimmenHochrechnerHilfsfunktionen.notNull;

public class AbstandZwischenGebietenAnhandMehrereMethoden implements AbstandGetter<Double> {
  private final List<AbstandGetter<Double>> abstandGettersZwischenGebieten;
  private Boolean isDefiniert = null;

  public AbstandZwischenGebietenAnhandMehrereMethoden(List<AbstandGetter<Double>> abstandGettersZwischenGebieten) {
    this.abstandGettersZwischenGebieten = abstandGettersZwischenGebieten;
  }

  @Override
  public boolean isDefiniert() {
    return this.isDefiniert != null && this.isDefiniert;
  }

  @Override
  public Double getAbstandWennDefiniert(GebietDaten<Double> g1, GebietDaten<Double> g2, KoordinatenInformationen koordinatenInformationen) {
    double result = 0;
    for (AbstandGetter<Double> abstandGetter: abstandGettersZwischenGebieten) {
      Long gewicht = abstandGetter.getGewicht();
      if (notNull(gewicht) != 0) {
        Double abstand = abstandGetter.getAbstandWennDefiniert(g1, g2, koordinatenInformationen);
        result += gewicht * notNull(abstand);
      }
    }
    return result;
  }

  @Override
  public void setGewicht(Long gewicht) {
    // do nothing
  }

  @Override
  public boolean setIsDefiniert(KoordinatenInformationen koordinatenInformationen) {
    this.isDefiniert = true;
    for (AbstandGetter<Double> abstandGetter: abstandGettersZwischenGebieten) {
      this.isDefiniert = this.isDefiniert && isAbstandGetterDefiniertOderHatZeroGewicht(koordinatenInformationen, abstandGetter);
    }
    return this.isDefiniert;
  }

  private boolean isAbstandGetterDefiniertOderHatZeroGewicht(KoordinatenInformationen koordinatenInformationen, AbstandGetter<Double> abstandGetter) {
    return notNull(abstandGetter.getGewicht()) == 0 || abstandGetter.setIsDefiniert(koordinatenInformationen);
  }

  @Override
  public AbstandartZwischenGebieten getAbstandartZwischenGebieten() {
    return AbstandartZwischenGebieten.MISCHUNG_MIT_BENUTZER_DEFINIERTE_GEWICHTUNG;
  }

  @Override
  public void addObservingProperties(FormBuilder formBuilder, LambdaEnumProperty observedProperty, BiFunction<String, Object[], String> messageGetter) {
    abstandGettersZwischenGebieten.forEach(abstandGetter -> {
      abstandGetter.addObservingGewichtProperty(formBuilder, observedProperty, messageGetter);
      //abstandGetter.addObservingProperties(formBuilder, observedProperty, messageGetter, koordinatenInformationen);
    });
  }
}
