
package de.ivu.elect.presentation.stimmeingabe.form;

import java.util.List;

import javax.inject.Inject;

import de.ivu.elect.business.gruppe.boundary.PolitischeGruppeDAO;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.stimmeingabe.boundary.plausi.StimmeingabePlausiDefinitionsResolver;
import de.ivu.elect.business.stimmeingabe.control.plausi.StimmeingabePlausiFormatter;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiFehlerart;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiGebietsart;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiKonfiguration;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiKonfigurationCustomData;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiKonfigurationCustomDataKategorie;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiKonfigurationProperties;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabePlausiKonfigurationPropertyContext;
import de.ivu.elect.business.stimmen.boundary.StimmeLabelMessages;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.presentation.dynamicform.AbstractStringProperty;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaEnumProperty;
import de.ivu.elect.jee.presentation.dynamicform.Property;
import de.ivu.elect.jee.presentation.dynamicform.PropertyType;
import de.ivu.elect.presentation.ViewFormBuilder;
import de.ivu.elect.presentation.gruppe.GruppeSchluesselFormatter;

public class StimmeingabePlausiKonfigurationViewFormBuilder extends ViewFormBuilder {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient StimmeLabelMessages stimmeLabelMessages;

  @Inject
  private transient StimmeingabePlausiDefinitionsResolver stimmeingabePlausiDefinitionsResolver;

  @Inject
  private transient PolitischeGruppeDAO politischeGruppeDAO;

  @Inject
  private transient GruppeSchluesselFormatter gruppeSchluesselFormatter;

  protected LambdaEnumProperty<StimmeingabePlausiGebietsart> gebietsartProperty;

  protected AbstractStringProperty fehlerschluesselProperty;

  public StimmeingabePlausiKonfigurationViewFormBuilder() {
    super();
  }

  public void addProperties(FormBuilder formBuilder, StimmeingabePlausiKonfiguration stimmeingabePlausiKonfiguration) {
    addProperties(formBuilder, stimmeingabePlausiKonfiguration, false);
  }

  public void addProperties(FormBuilder formBuilder, StimmeingabePlausiKonfiguration stimmeingabePlausiKonfiguration, boolean readonly) {
    StimmeingabePlausiKonfigurationProperties stimmeingabePlausiKonfigurationProperties = stimmeingabePlausiKonfiguration.getProperties();

    formBuilder.addProperty(stimmeingabePlausiKonfigurationProperties.getErgebniseingangsartProperty()).readonly();

    gebietsartProperty = stimmeingabePlausiKonfigurationProperties.getGebietsartProperty();
    formBuilder.addProperty(gebietsartProperty).readonly();

    // Lokalisisierte Werte erstmal nicht bearbeitbar machen, sondern immer aus den Messages laden, cf. StimmeingabePlausiKonfigurationCreate#save, StimmeingabePlausiKonfigurationEdit#save!!!
    fillInStimmeingabePlausiKonfigurationValuesLocalizated(stimmeingabePlausiKonfiguration);

    PropertyType propertiesLocalizedType = PropertyType.INPUT_TEXTAREA;
    boolean propertiesLocalizedReadonly = true;

    formBuilder.addProperty(stimmeingabePlausiKonfigurationProperties.getBeschreibungProperty()).withType(propertiesLocalizedType).withReadonly(readonly || propertiesLocalizedReadonly);

    AbstractStringProperty fehlermeldungFormatProperty = stimmeingabePlausiKonfigurationProperties.getFehlermeldungFormatProperty();
    fehlermeldungFormatProperty.setValue(stimmeingabePlausiKonfiguration.formatFehlermeldung(new StimmeingabePlausiFormatter(stimmeLabelMessages)));

    formBuilder.addProperty(fehlermeldungFormatProperty).withType(propertiesLocalizedType).withReadonly(readonly || propertiesLocalizedReadonly);

    boolean isDefaultMussFehler = isDefaultFehlerartError(stimmeingabePlausiKonfiguration);

    LambdaEnumProperty<StimmeingabePlausiFehlerart> fehlerartProperty = stimmeingabePlausiKonfigurationProperties.getFehlerartProperty();
    fehlerartProperty.setValueFilter(fehlerart -> !fehlerart.isUnbekannt());
    formBuilder.addProperty(fehlerartProperty).withReadonly(readonly || isDefaultMussFehler);

    boolean deaktivierenVerboten = isDefaultMussFehler && !hasUseCasePermission(UseCasePermission.STIMMEINGABE_PLAUSI_MUSS_FEHLER_DEAKTIVIEREN);
    formBuilder.addProperty(stimmeingabePlausiKonfigurationProperties.getStatusProperty()).withReadonly(readonly || deaktivierenVerboten);

    fehlerschluesselProperty = stimmeingabePlausiKonfigurationProperties.getFehlerschluesselProperty();
    formBuilder.addProperty(fehlerschluesselProperty).withReadonly(readonly);

    StimmeingabePlausiKonfigurationCustomData customData = stimmeingabePlausiKonfiguration.getCustomData(StimmeingabePlausiKonfigurationCustomData.class);
    StimmeingabePlausiKonfigurationPropertyContext context = new StimmeingabePlausiKonfigurationPropertyContext(stimmeingabePlausiKonfiguration.getWahl(), politischeGruppeDAO, gruppeSchluesselFormatter, getMessages());
    for (StimmeingabePlausiKonfigurationCustomDataKategorie kategorie : StimmeingabePlausiKonfigurationCustomDataKategorie.values()) {
      List<Property> customDataProperties = customData.getProperties(context).get(kategorie);
      if (customDataProperties != null) {
        for (Property customDataProperty : customDataProperties) {
          formBuilder.addProperty(customDataProperty).withReadonly(readonly);
        }
      }
    }
  }

  private boolean isDefaultFehlerartError(StimmeingabePlausiKonfiguration stimmeingabePlausiKonfiguration) {
    boolean isDefaultMussFehler = stimmeingabePlausiKonfiguration.isFehlerartError();
    if (stimmeingabePlausiKonfiguration.getStimmeingabePlausiKonfigurationDefault() != null) {
      isDefaultMussFehler = stimmeingabePlausiKonfiguration.getStimmeingabePlausiKonfigurationDefault().isFehlerartError();
    }
    return isDefaultMussFehler;
  }

  private void fillInStimmeingabePlausiKonfigurationValuesLocalizated(StimmeingabePlausiKonfiguration stimmeingabePlausiKonfiguration) {
    Wahl wahl = stimmeingabePlausiKonfiguration.getWahl();

    stimmeingabePlausiDefinitionsResolver.findStimmeingabePlausiDefinitions(wahl)
        .ifPresent(stimmeingabePlausiDefinition -> stimmeingabePlausiDefinition.fillInStimmeingabePlausiKonfigurationValuesLocalizated(wahl.getWahlart(), stimmeingabePlausiKonfiguration));
  }
}
