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

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;

import de.ivu.elect.business.benutzerverwaltung.entity.Benutzer;
import de.ivu.elect.business.benutzerverwaltung.entity.BenutzerProperties;
import de.ivu.elect.business.benutzerverwaltung.entity.RolleConstants;
import de.ivu.elect.business.konfiguration.entity.KonfigurationExtendedLoader;
import de.ivu.elect.business.konfiguration.entity.MandantKonfigurationWerte;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.security.entity.TwoFactorAuthenticationStatus;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.LambdaBooleanProperty;
import de.ivu.elect.jee.presentation.dynamicform.PropertyType;
import de.ivu.elect.jee.security.LoginServiceFactory;

@RequestScoped
public class BenutzerViewFormBuilder extends AbstractEntityMitRollenViewFormBuilder {

  private static final long serialVersionUID = 1L;

  @Inject
  protected transient BenutzerUniqueUKFacesValidator benutzerUniqueTKFacesValidator;

  @Inject
  private transient LoginServiceFactory loginServiceFactory;

  @Inject
  private transient KonfigurationExtendedLoader konfigurationExtendedLoader;

  public BenutzerViewFormBuilder() {
    super();
  }

  public void addProperties(FormBuilder formBuilder, Benutzer benutzer) {
    BenutzerProperties benutzerProperties = benutzer.getProperties();

    addBenutzerkennungProperty(formBuilder, benutzer);
    formBuilder.addProperty(benutzerProperties.getVornameProperty());
    formBuilder.addProperty(benutzerProperties.getFamiliennameProperty());
    addPasswordProperty(formBuilder);

    if (benutzer.isPersistent()) {
      formBuilder.addProperty(benutzerProperties.getMussPasswortWechselnProperty()).withReadonly(!isPasswortAendernMoeglich(benutzer));

      addTfaProperties(formBuilder, benutzer);
    }

    addGesperrtProperty(formBuilder, benutzer);
    formBuilder.addProperty(benutzerProperties.getBemerkungProperty()).withType(PropertyType.INPUT_TEXTAREA);

    formBuilder.addSeparator(RolleConstants.MESSAGE_KEY_ENTITY_MEHRZAHL);
    addRolleProperties(formBuilder, benutzer.getRolles(), benutzer.getMandant());
  }

  protected void addGesperrtProperty(FormBuilder formBuilder, Benutzer benutzer) {
    formBuilder.addProperty(benutzer.getProperties().getGesperrtProperty()).withReadonly(isSperrenMoeglich(benutzer));
  }

  protected void addPasswordProperty(FormBuilder formBuilder) {
    // NOTE, dass an dieser Stelle die Eingabefelder für das Passwort und dessen Wiederholung eingefügt werden,
    // cf. <ui:define name="between" /> in benutzerverwaltung/benutzer-create.xhtml!
    formBuilder.addProperty(new PasswordPlatzhalterProperty());
  }

  protected void addBenutzerkennungProperty(FormBuilder formBuilder, Benutzer benutzer) {
    formBuilder.addProperty(benutzer.getProperties().getBenutzerkennungProperty()).withValidatorAndPk(benutzerUniqueTKFacesValidator, benutzer.getPk()).withReadonly(!isBenutzernameKannGewechseltWerden(benutzer));
  }

  private void addTfaProperties(FormBuilder formBuilder, Benutzer benutzer) {
    TwoFactorAuthenticationStatus twoFactorAuthenticationStatus = konfigurationExtendedLoader.resolveEnumValue(benutzer.getMandant(), MandantKonfigurationWerte.TWO_FACTOR_AUTHENTICATION_STATUS, TwoFactorAuthenticationStatus.class);
    if (twoFactorAuthenticationStatus != null &&  twoFactorAuthenticationStatus.isAktiv()) {
      formBuilder.addProperty(new LambdaBooleanProperty(getMessage("tfa.benutzer.tan.liste.konfiguriert"), false, b -> {
        if (!b) {
          benutzer.setTanliste("");
        }

      }, benutzer::isTanListeKonfiguriert)).withReadonly(!benutzer.isTanListeKonfiguriert());

      formBuilder.addProperty(new LambdaBooleanProperty(getMessage("tfa.benutzer.totp.konfiguriert"), false, b -> {
        if (!b) {
          benutzer.setHotpSecret("");
        }

      }, benutzer::isHotpKonfiguriert)).withReadonly(!benutzer.isHotpKonfiguriert());
    }
  }

  public boolean isPasswortAendernMoeglich(Benutzer benutzer) {
    return loginServiceFactory.isPasswortWechselnMoeglich(benutzer.getMandantenNummer()) || loginServiceFactory.isAdminUser(benutzer);
  }

  public String getPasswortFormatPattern(Mandant mandant) {
    return loginServiceFactory.getPasswortFormatPattern(mandant.getNummer());
  }

  public String getPasswortFormatBeschreibung(Mandant mandant) {
    return loginServiceFactory.getPasswortFormatBeschreibung(mandant.getNummer());
  }

  protected boolean isSperrenMoeglich(Benutzer benutzer) {
    return getPrincipal().getLogin().equals(benutzer) || !loginServiceFactory.isSperrenMoeglich(benutzer.getMandantenNummer());
  }

  protected boolean isBenutzernameKannGewechseltWerden(Benutzer benutzer) {
    return loginServiceFactory.isBenutzernameKannGewechseltWerden(benutzer);
  }

  @Override
  protected boolean isGruppenUebernehmen(Mandant mandant) {
    return loginServiceFactory.isGruppenUebernehmen(mandant.getNummer());
  }
}
