
package de.ivu.elect.presentation.security.sso;

import java.util.List;

import javax.enterprise.context.RequestScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.AuthenticationException;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.business.security.control.SingleSignOn;
import de.ivu.elect.jee.faces.FacesContextUtil;
import de.ivu.elect.jee.presentation.security.StartViewResolver;
import de.ivu.elect.jee.security.AuthentificationFailedException;
import de.ivu.elect.jee.security.IpHostname;
import de.ivu.elect.jee.security.LoginData;
import de.ivu.elect.jee.security.LoginGruppe;
import de.ivu.elect.jee.security.LoginIpBestimmer;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.hilfe.KeineOnlineHilfe;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.security.LoginGewuenschteSeite;
import de.ivu.elect.presentation.security.LoginView;
import de.ivu.elect.presentation.security.MandantenNummerUrlParameter;


import static org.apache.commons.lang3.StringUtils.isNotBlank;

@Named
@RequestScoped
@OnlineHilfeId(KeineOnlineHilfe.KEINE_ONLINE_HILFE)
@View(viewId = SingleSignOnView.VIEW_ID, useCase = UseCasePermission.OHNE)
public class SingleSignOnView {

  private static final Logger LOG = LoggerFactory.getLogger(SingleSignOnView.class);

  public static final String VIEW_ID = "/single-sign-on.xhtml";

  @Inject
  private transient SingleSignOn singleSignOn;

  @Inject
  private transient StartViewResolver startViewResolver;

  @Inject
  private transient ElectCommonPrincipal electCommonPrincipal;

  @Inject
  private transient LoginGewuenschteSeite loginGewuenschteSeite;

  @Inject
  private transient LoginIpBestimmer loginIpBestimmer;

  @Inject
  private transient MandantenNummerUrlParameter mandantenNummerUrlParameter;

  public void checkSingleSignOn() {
    IpHostname ipHostname = loginIpBestimmer.bestimmeIpAdresseAusRequest();
    if (electCommonPrincipal.isLoggedIn()) {
      LOG.info("Bereits eingeloggt: " + electCommonPrincipal.getLogin().getBenutzerkennung() + ", ipHostname=" + ipHostname);
      FacesContextUtil.redirectToView(startViewResolver.getStartViewId());
      return;
    }
    boolean singleSignOnLoginErfolgreich = false;
    String remoteUser = null;
    if (singleSignOn.isSingleSignOnAktiviert()) {

      Object request = FacesContext.getCurrentInstance().getExternalContext().getRequest();
      if (request instanceof HttpServletRequest) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        if (httpServletRequest.getUserPrincipal() != null
            && singleSignOn.isRequiredPrincipal(httpServletRequest.getUserPrincipal())
            && isNotBlank(httpServletRequest.getRemoteUser())) {
          remoteUser = httpServletRequest.getRemoteUser();
          try {
            Long mandantenNummer = mandantenNummerUrlParameter.bestimmeMandantenNummerAusContext();
            if (mandantenNummer == null) {
              LOG.warn("Single Sign-on fehlgeschlagen Mandant nicht in URL enthalten " + remoteUser + ", ipHostname=" + ipHostname);
              singleSignOnLoginErfolgreich = false;
            } else {
              LOG.info("Single Sign-on für: " + remoteUser + ", Mandant: " + mandantenNummer + ", ipHostname=" + ipHostname);
              List<LoginGruppe> gruppen = singleSignOn.bestimmeActiveDirectoryGruppen(mandantenNummer, remoteUser);
              electCommonPrincipal.login(new LoginData(mandantenNummer, remoteUser, "", "", true, false, false, gruppen, null, 0), ipHostname);
              singleSignOnLoginErfolgreich = true;
            }
          } catch (AuthentificationFailedException e) {
            LOG.warn("Single Sign-on fehlgeschlagen für " + remoteUser + ", ipHostname=" + ipHostname + ", Nachricht: " + e.getMessage());
            singleSignOnLoginErfolgreich = false;
          } catch (AuthenticationException e) {
            LOG.error("Single Sign-on fehlgeschlagen, Pre-Auth-Benutzer nicht berechtigt?" + " IpHostname=" + ipHostname, e);
            singleSignOnLoginErfolgreich = false;
          } catch (NamingException e) {
            LOG.error("Single Sign-on fehlgeschlagen" + " IpHostname=" + ipHostname, e);
            singleSignOnLoginErfolgreich = false;
          }
        }
      }
    }
    if (singleSignOnLoginErfolgreich) {
      LOG.info("Single Sign-on erfolgreich für: " + remoteUser + ", ipHostname=" + ipHostname);
      loginGewuenschteSeite.redirectAfterLogin();
    } else {
      FacesContextUtil.redirectToView(LoginView.VIEW_ID);
    }
  }
}
