package com.oguerreiro.resilient.domain;

import java.io.Serializable;

import jakarta.persistence.Column;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Version;

/**
 * 
 * @param <T>  Entity Domain type class
 * @param <ID> Entity Domain key type class
 */
@MappedSuperclass
public abstract class AbstractResilientEntity<T extends AbstractResilientEntity<T, ID>, ID> implements Serializable {
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private ID id;

  /**
   * Record version for concurrency control.
   */
  @Version
  @Column(name = "version")
  private Integer version;

  protected abstract ID getId();

  protected abstract T id(ID id);

  protected abstract void setId(ID id);

  public Integer getVersion() {
    return this.version;
  }

  // This is a safe cast, since its GUARANTEED that DOMAIN is always a subclass of  AbstractEntity
  @SuppressWarnings("unchecked")
  public T version(Integer version) {
    this.setVersion(version);
    return (T) this;
  }

  public void setVersion(Integer version) {
    this.version = version;
  }

  @Override
  public int hashCode() {
    // see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
    return getClass().hashCode();
  }
}
