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

import static java.util.Objects.isNull;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.annotation.Nullable;
import javax.inject.Inject;

import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.staat.boundary.StaatExtendedDAO;
import de.ivu.elect.business.staat.boundary.StaatFactory;
import de.ivu.elect.business.staat.boundary.StaatFinder;
import de.ivu.elect.business.staat.control.StaatByNameStaatsangehoerigkeitInlandZuerstComparator;
import de.ivu.elect.business.staat.entity.AbstractStaat;
import de.ivu.elect.business.staat.entity.Staat;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.Property;
import de.ivu.elect.presentation.ViewFormBuilder;

public abstract class AbstractPersonenregisterPropertiesViewFormBuilder extends ViewFormBuilder {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient StaatExtendedDAO staatExtendedDAO;

  @Inject
  private transient StaatFactory staatFactory;

  @Inject
  private transient StaatFinder staatFinder;

  private Staat defaultStaatsangehoerigkeit;

  private Staat emptyStaatsangehoerigkeit;

  private List<Staat> staatsangehoerigkeiten;

  protected AbstractPersonenregisterPropertiesViewFormBuilder() {
    super();
  }

  public boolean isPersonenregisterAbgeglichenAndNotPersonenregisterAbgleichUeberschreibbar(Personendaten personendaten) {
    return personendaten.isPersonenregisterAbgeglichen() && !isPersonenregisterAbgleichUeberschreibbar();
  }

  public FormBuilder addPersonenregisterProperty(FormBuilder formBuilder, @Nullable Personendaten personendaten, Property property, boolean propertyReadonly,
      Collection<Class< ? extends Property>> personenregisterPropertiesUebernommen, boolean personenregisterPropertyReadonly) {
    return addPersonenregisterProperty(formBuilder, personendaten, property, false, propertyReadonly, personenregisterPropertiesUebernommen, personenregisterPropertyReadonly);
  }

  public FormBuilder addPersonenregisterProperty(FormBuilder formBuilder, @Nullable Personendaten personendaten, Property property, boolean visibleOnPageLoad, boolean propertyReadonly,
      Collection<Class< ? extends Property>> personenregisterPropertiesUebernommen, boolean personenregisterPropertyReadonly) {
    boolean readonly = isPersonenregisterPropertyReadonly(personendaten, property, propertyReadonly, personenregisterPropertiesUebernommen, personenregisterPropertyReadonly);

    FormBuilder result = formBuilder.addProperty(property);

    if (visibleOnPageLoad) {
      result = result.visibleOnPageLoad();
    }

    return result.withReadonly(readonly);
  }

  protected boolean isPersonenregisterPropertyReadonly(Personendaten personendaten, Property property, boolean propertyReadonly,
      Collection<Class< ? extends Property>> personenregisterPropertiesUebernommen, boolean personenregisterPropertyReadonly) {
    return propertyReadonly || isPersonenregisterPropertyReadonlySupported(personendaten, personenregisterPropertyReadonly)
        && isPersonenregisterPropertyUebernommen(personendaten, personenregisterPropertiesUebernommen, property);
  }

  protected boolean isPersonenregisterPropertyReadonlySupported(Personendaten personendaten, boolean personenregisterPropertyReadonly) {
    return personenregisterPropertyReadonly && personendaten != null && personendaten.hasOrdnungsmerkmal() && !isPersonenregisterAbgleichUeberschreibbar();
  }

  protected boolean isPersonenregisterAbgleichUeberschreibbar() {
    return hasUseCasePermission(UseCasePermission.PERSONENREGISTER_ATTRIBUT_UEBERSCHREIBEN);
  }

  private boolean isPersonenregisterPropertyUebernommen(Personendaten personendaten, Collection<Class< ? extends Property>> personenregisterPropertiesUebernommen, Property property) {
    return personenregisterPropertiesUebernommen.contains(property.getClass());
  }

  @Deprecated //  ELECT-4622
  public abstract Collection<Class< ? extends Property>> getPersonenregisterPropertiesUebernommen(Personendaten personendaten);

  public Staat getDefaultStaatsangehoerigkeit() {
    if (defaultStaatsangehoerigkeit == null) {
      defaultStaatsangehoerigkeit = staatFinder.findUniqueStaatByLocale(staatExtendedDAO, AbstractStaat.DEUTSCHLAND_LOCALE);
    }

    return defaultStaatsangehoerigkeit;
  }

  protected Staat getEmptyStaatsangehoerigkeit() {
    if (emptyStaatsangehoerigkeit == null) {
      emptyStaatsangehoerigkeit = staatFactory.create();
    }

    return emptyStaatsangehoerigkeit;
  }

  public void tryAttachStaatsangehoerigkeiten(Personendaten personendaten) {
    staatFinder.tryAttachStaatsangehoerigkeitenOrIgnore(staatExtendedDAO, personendaten);
  }

  protected List<Staat> findAllStaatsangehoerigkeiten() {
    if (isNull(staatsangehoerigkeiten)) {
      staatsangehoerigkeiten = staatExtendedDAO.findByAllHavingCustomCodeStaatsangehoerigkeit();

      Collections.sort(staatsangehoerigkeiten, new StaatByNameStaatsangehoerigkeitInlandZuerstComparator());
    }

    return staatsangehoerigkeiten;
  }

  protected Staat tryFindStaatsangehoerigkeit(String codeStaatsangehoerigkeit) {
    return staatFinder.tryFindUniqueStaat(staatExtendedDAO, codeStaatsangehoerigkeit);
  }
}
