
package de.ivu.elect.presentation.edit;

import static de.ivu.elect.jee.entity.EntityUtil.castTo;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PreDestroy;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpSession;

import org.apache.deltaspike.core.api.scope.ViewAccessScoped;

import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.person.entity.PersonenregisterAbgleichStatus;
import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.jee.concurrent.GleichzeitigBearbeitenController;
import de.ivu.elect.jee.concurrent.GleichzeitigBearbeitenEntity;
import de.ivu.elect.jee.entity.Entity;
import de.ivu.elect.jee.entity.EntityLongPK;
import de.ivu.elect.jee.entity.EntityTechnicalNamePk;
import de.ivu.elect.jee.faces.FacesMessageUtil;
import de.ivu.elect.jee.faces.UserLocale;

@ViewAccessScoped
public abstract class AbstractViewScopeStore<E extends Entity<K, ? >, K extends EntityLongPK> implements Serializable {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient ElectCommonPrincipal principal;

  @Inject
  private transient GleichzeitigBearbeitenController gleichzeitigBearbeitenController;

  @Inject
  private transient UserLocale userLocale;

  private String sessionId;

  private EntityTechnicalNamePk entityKey;

  protected AbstractViewScopeStore() {
    super();
  }

  public void setEntity(E entity) {
    if (entity != null) {
      EntityTechnicalNamePk entityTechnicalNamePk = new EntityTechnicalNamePk(entity);

      if (!entityTechnicalNamePk.equals(entityKey)) {
        cleanUp(); // Vorherige Entität entfernen

        entityKey = entityTechnicalNamePk;

        if (!FacesContext.getCurrentInstance().isPostback()) {
          for (GleichzeitigBearbeitenEntity otherUser : registerAndCollectAllOtherGleichzeitigBearbeitenEntities(entityKey)) {
            addWarnMessage(otherUser);
          }

          if (entity.isInstanceOf(Personendaten.class)) {
            Personendaten personendaten = castTo(entity, Personendaten.class);

            if (personendaten.isPersonStatusUngeprueft()) {
              PersonenregisterAbgleichStatus personenregisterAbgleichStatus = personendaten.getPersonenregisterAbgleichStatus();

              if (personenregisterAbgleichStatus != null && personenregisterAbgleichStatus.isAbgleichNotwendig()) { // ELECTDD-680
                addWarnMessage("entity.gleichzeitig.personenregister.abgleich");
              }
            }
          }
        }
      }
    }
  }

  private List<GleichzeitigBearbeitenEntity> registerAndCollectAllOtherGleichzeitigBearbeitenEntities(EntityTechnicalNamePk entityKey) {
    return gleichzeitigBearbeitenController.registerAndCollectAllOtherGleichzeitigBearbeitenEntities(getSessionId(), getBenutzerNameFormatted(), entityKey);
  }

  @PreDestroy
  public void cleanUp() {
    if (entityKey != null) {
      try {
        gleichzeitigBearbeitenController.unregister(getSessionId(), entityKey);
      } catch (Exception ignored) {
      }
    }
  }

  private String getSessionId() {
    if (sessionId == null) {
      try {
        Object session = FacesContext.getCurrentInstance().getExternalContext().getSession(false);

        if (session instanceof HttpSession) {
          sessionId = ((HttpSession) session).getId();
        }
      } catch (Exception ignored) {
      }
    }

    return sessionId;
  }

  private String getBenutzerNameFormatted() {
    return principal.getFormattedName();
  }

  protected void addWarnMessage(GleichzeitigBearbeitenEntity otherUser) {
    addWarnMessage(getMessageKey(), otherUser.getGeoeffnetDurch(), userLocale.formatTime(otherUser.getGeoeffnetAm()));
  }

  protected String getMessageKey() {
    return "entity.gleichzeitig.bearbeitet";
  }

  protected void addWarnMessage(String msgKey, Object... params) {
    FacesMessageUtil.addWarnMessage(msgKey, params);
  }

  protected String getMessage(Enum< ? > enumValue) {
    return getMessage(FacesMessageUtil.getEnumMessageKey(enumValue));
  }

  protected String getMessage(String msgKey, Object... params) {
    return FacesMessageUtil.getResourceText(msgKey, params);
  }
}
