
package de.ivu.elect.jee.entity;

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

import de.ivu.elect.jee.entity.tk.EntityTK;
import de.ivu.elect.jee.entity.tk.EntityUK;
import de.ivu.elect.jee.protokollierung.AttributWertVorher;
import de.ivu.elect.jee.protokollierung.VorherNachherWert;

/**
 * Marker interface für Entities
 *
 */
public interface Entity<PK, UK extends EntityUK> extends Serializable {

  Long getId();

  PK getPk();

  UK getUk();

  Class<?> getEntityClass();

  EntityTK getTk();

  // ELECT-1610 Name der entität im Log der Änderungen
  String getEntityTechnicalName();

  // ELECT-1610 sollen überhaupt Änderungen protokolliert werden?
  boolean isAenderungenProtokollieren();

  // ELECT-1610 Map aller Attribut-Namen und deren veränderte Werte
  Map<String, VorherNachherWert> getProtokollierteAttributeMitWerten();

  // ELECT-5532 und Werte wieder setzen...
  void setProtokollierteAttributeMitWerten(Map<String, AttributWertVorher> werteVorher);

  // ELECT-1610 zurücksetzen der zu protokollierenden Änderungen
  void resetProtokollierteAttribute();

  /**
   * Entitäten, die fachlich zu dieser Entität gehören, aber in einer eigenen Entität gespeichert sind (z.B. Anschrift
   * an Person)
   */
  List<EntityFachlichAbhaengigNode> getFachlichAbhaengigeEntitaeten();

  /**
   * Hintergund dieser Methode, ist das Problem mit Hibernate Proxy-Klassen, die ein instanceof erfolgreich verhindern
   * Siehe auch: http://stackoverflow.com/questions/7586991/jsf-jpa-hibernate-proxy-inheritance-issue
   */
  boolean isInstanceOf(Class<?> clazz);

  /**
   * Hintergund dieser Methode, ist das Problem mit Hibernate Proxy-Klassen, die ein casten erfolgreich verhindern
   * Siehe auch: http://stackoverflow.com/questions/7586991/jsf-jpa-hibernate-proxy-inheritance-issue
   * <p>
   * !!! Ganz wichtig, die Entität kann NICHT direkt zurückgegeben werden, da sie durch Hibernate beim Aufruf der
   * Methode wieder durch ihren Proxy ersetzt wird - daher ist der EntityContainer notwendig!!!
   */
  <E> EntityContainer<E> castTo(Class<E> clazz);

  /*
  * ELECT-3796
  * Name Klasse der Entität oder Name der Basisklasse der Entität bei vererbten Entitäten, es gilt für Entitäten E1 und E2=
   * E1.equals(E2) <=> E1.getId().equals(E2.getId) && E1.getBaseClassName().equals(E2.getBaseClassName)
   * spart aufwendige "instanceof Konstruktionen"
   */
  String getBaseClassName();

  void copyEntityAttributesToOtherEntity(Entity other);


  default Map<String, VorherNachherWert> createEmptyProtokollierteAttributeMitWertenMap(){
    return new HashMap<>();
  }

  default java.util.Set<de.ivu.elect.jee.entity.EntityConstraintViolation> validateEntity() {
    return Collections.emptySet();
  }

}
