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

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.benutzerverwaltung.boundary.BenutzerDAO;
import de.ivu.elect.business.benutzerverwaltung.boundary.BenutzerFactory;
import de.ivu.elect.business.benutzerverwaltung.boundary.RolleDAO;
import de.ivu.elect.business.benutzerverwaltung.control.BenutzerCreate;
import de.ivu.elect.business.benutzerverwaltung.control.RolleCreate;
import de.ivu.elect.business.benutzerverwaltung.entity.Benutzer;
import de.ivu.elect.business.benutzerverwaltung.entity.Rolle;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.jee.security.LoginData;
import de.ivu.elect.jee.security.LoginGruppe;
import de.ivu.elect.util.ElectRandom;

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class PrincipalBenutzerCreator implements Serializable {

  private static final String EXTERN_SALT = "EXTERN_SALT";

  private static final String EXTERN_PASSWORT = "EXTERN_PASSWORT";

  private static final long serialVersionUID = 1L;

  @Inject
  private transient BenutzerFactory benutzerFactory;

  @Inject
  private transient BenutzerDAO benutzerDAO;

  @Inject
  private transient BenutzerCreate benutzerCreate;

  @Inject
  private transient RolleDAO rolleDAO;

  @Inject
  private transient RolleCreate rolleCreate;

  @Inject
  private transient BenutzerRollenCreateFilter benutzerRollenCreateFilter;

  public Benutzer createBenutzer(Mandant mandant, LoginData loginData) {
    Benutzer benutzer = benutzerFactory.create();
    benutzer.setBenutzerkennung(loginData.getBenutzerkennung());
    benutzer.setFamilienname(loginData.getNachname());
    benutzer.setVorname(loginData.getVorname());
    benutzer.setSalt(EXTERN_SALT + ElectRandom.getRandom().nextDouble());
    benutzer.setPasswort(EXTERN_PASSWORT + ElectRandom.getRandom().nextDouble());
    benutzer.setGesperrt(loginData.isGesperrt());
    benutzer.setMussPasswortWechseln(loginData.isMussPasswortWechseln());
    benutzer.setMandant(mandant);
    benutzerCreate.saveMitEinstellungen(benutzer);
    benutzerDAO.flush();
    return benutzer;
  }

  public List<Rolle> findeRollenOderLegeAn(Benutzer benutzerNotAttached, List<LoginGruppe> loginGruppen) {
    Benutzer benutzer = benutzerDAO.attach(benutzerNotAttached);
    benutzerRollenCreateFilter.aktualisiereBenutzer(benutzer, loginGruppen);
    return findeRollenOderLegeAnGefiltert(benutzer.getMandant(), benutzerRollenCreateFilter.filterLoginGruppen(loginGruppen));
  }

  protected List<Rolle> findeRollenOderLegeAnGefiltert(Mandant mandant, List<LoginGruppe> loginGruppen) {
    Map<String, Rolle> rollenImSystemNachName = bestimmeRollenImSystem(mandant);
    List<Rolle> result = new ArrayList<>();
    for (LoginGruppe loginGruppe : loginGruppen) {
      if (StringUtils.isNotEmpty(loginGruppe.getName())) {
        Rolle rolle = rollenImSystemNachName.get(loginGruppe.getName().toUpperCase());
        if (rolle == null) {
          rolle = new Rolle();
          rolle.setMandant(mandant);
          rolle.setBeschreibung(loginGruppe.getBeschreibung());
          rolle.setName(loginGruppe.getName());
          rolleCreate.save(rolle);
          rollenImSystemNachName.put(rolle.getName().toUpperCase(), rolle);
        }
        result.add(rolle);
      }
    }
    return result;
  }

  private Map<String, Rolle> bestimmeRollenImSystem(Mandant mandant) {
    Map<String, Rolle> result = new HashMap<>();

    for (Rolle rolle : rolleDAO.findByAll(mandant)) {
      result.put(rolle.getName().toUpperCase(), rolle);
    }

    return result;
  }
}
