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

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import de.ivu.elect.business.veranstaltung.boundary.VeranstaltungExtendedDAO;
import de.ivu.elect.business.veranstaltung.control.VeranstaltungByBezeichnungComparator;
import de.ivu.elect.business.veranstaltung.entity.Veranstaltung;
import de.ivu.elect.business.veranstaltung.entity.VeranstaltungArt;
import de.ivu.elect.business.veranstaltung.entity.VeranstaltungMeta;
import de.ivu.elect.business.veranstaltung.entity.VeranstaltungProperties;
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.jee.presentation.dynamicform.SelectOneMenuProperty;
import de.ivu.elect.jee.presentation.dynamicform.TimestampDateProperty;
import de.ivu.elect.jee.presentation.dynamicform.TimestampTimeProperty;
import de.ivu.elect.presentation.ViewFormBuilder;
import de.ivu.elect.presentation.anschrift.form.AnschriftViewFormBuilder;
import de.ivu.elect.presentation.person.AnsprechpartnerViewFormBuilder;

public class VeranstaltungViewFormBuilder extends ViewFormBuilder {

  private static final long serialVersionUID = 1L;

  private static final long EINE_STUNDE_IN_MS = TimeUnit.HOURS.toMillis(1);

  @Inject
  private VeranstaltungExtendedDAO veranstaltungDao;

  @Inject
  private VeranstaltungMeta veranstaltungMeta;

  @Inject
  private AnschriftViewFormBuilder anschriftViewFormBuilder;

  @Inject
  private AnsprechpartnerViewFormBuilder ansprechpartnerViewFormBuilder;

  public VeranstaltungViewFormBuilder() {
    super();
  }

  public void addProperties(FormBuilder formBuilder, Veranstaltung veranstaltung) {
    VeranstaltungProperties veranstaltungProperties = veranstaltung.getProperties();

    formBuilder.addProperty(veranstaltungProperties.getBezeichnungProperty());

    TimestampDateProperty beginnDatumProperty = new TimestampDateProperty(veranstaltungProperties.getBeginnProperty());
    formBuilder.addProperty(beginnDatumProperty);
    TimestampTimeProperty beginnUhrzeitProperty = new TimestampTimeProperty(veranstaltungProperties.getBeginnProperty());
    formBuilder.addProperty(beginnUhrzeitProperty);

    TimestampDateProperty endeDatumProperty = new TimestampDateProperty(veranstaltungProperties.getEndeProperty()) {

      @Override
      public void onObservedPropertyValueChanged(Property observedProperty) {
        if (!this.hasValue()) {
          this.setValue(((TimestampDateProperty) observedProperty).getValue());
        }
      }
    };

    formBuilder.addProperty(endeDatumProperty).withObservedProperty(beginnDatumProperty);
    TimestampTimeProperty endeUhrzeit = new TimestampTimeProperty(veranstaltungProperties.getEndeProperty()) {

      @Override
      public void onObservedPropertyValueChanged(Property observedProperty) {
        if (!this.hasValue()) {
          Date newValue = ((TimestampTimeProperty) observedProperty).getValue();
          if (newValue != null) {
            this.setValue(new Date(newValue.getTime() + EINE_STUNDE_IN_MS));
          }
        }
      }

    };

    formBuilder.addProperty(endeUhrzeit).withObservedProperty(beginnUhrzeitProperty);

    LambdaEnumProperty<VeranstaltungArt> veranstaltungArtProperty = veranstaltungProperties
        .getVeranstaltungArtMitLeererAuswahlProperty();
    formBuilder.addProperty(veranstaltungArtProperty).required();
    addSchulungArtProperty(formBuilder, veranstaltung, veranstaltungArtProperty);
    formBuilder.addProperty(veranstaltungProperties.getVeranstaltungStatusProperty());
    formBuilder.addProperty(veranstaltungProperties.getTeilnehmerAnzahlMaxProperty());
    formBuilder.addProperty(veranstaltungProperties.getBemerkungProperty()).withType(PropertyType.INPUT_TEXTAREA);

    formBuilder.addSeparator(veranstaltungMeta.getVerknuepfteVeranstaltungEinzahlMessageKey());
    formBuilder.addProperty(new VeranstaltungSelectOneMenuProperty(getVerknuepfbareVeranstaltungen(veranstaltung), true, veranstaltung));

    formBuilder.addSeparator(veranstaltungMeta.getAnschriftEinzahlMessageKey());
    formBuilder.addProperty(veranstaltungProperties.getRaumBezeichnungProperty());
    formBuilder.addProperty(veranstaltungProperties.getVeranstaltungOrtProperty());
    anschriftViewFormBuilder.addLokalitaetAnschriftProperties(formBuilder, veranstaltung.getAnschrift());

    formBuilder.addSeparator(veranstaltungMeta.getAnsprechpartnerEinzahlMessageKey());
    ansprechpartnerViewFormBuilder.addProperties(formBuilder, veranstaltung.getAnsprechpartner());
  }

  private void addSchulungArtProperty(FormBuilder formBuilder, Veranstaltung veranstaltung,
      SelectOneMenuProperty<VeranstaltungArt> veranstaltungArtProperty) {

    VeranstaltungSchulungArtProperty schulungArtProperty = new VeranstaltungSchulungArtProperty(veranstaltung);
    schulungArtProperty.appendObservedPropertyValueChangedConsumer(p -> {
      VeranstaltungArt veranstaltungArt = veranstaltungArtProperty.getValue();
      schulungArtProperty.setVisible(veranstaltungArt != null && veranstaltungArt.isSchulung());
    });
    schulungArtProperty.onObservedPropertyValueChanged(veranstaltungArtProperty); // HINT: Sichtbarkeit initial setzen

    formBuilder //
        .addProperty(schulungArtProperty) //
        .withObservedProperty(veranstaltungArtProperty);

  }

  private List<Veranstaltung> getVerknuepfbareVeranstaltungen(Veranstaltung veranstaltung) {
    List<Veranstaltung> result = new ArrayList<>();

    if (veranstaltung.getWahl() != null) {
      result.addAll(veranstaltungDao.findByWahlOrderByBeginn(veranstaltung.getWahl()));
    } else {
      result.addAll(veranstaltungDao.findByWahlterminOrderByBeginn(veranstaltung.getWahltermin()));
    }

    result.remove(veranstaltung);

    Collections.sort(result, new VeranstaltungByBezeichnungComparator());

    return result;
  }
}
