package com.oguerreiro.resilient.domain;

import org.hibernate.Hibernate;

import jakarta.persistence.Column;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import tech.jhipster.service.QueryService;

/**
 * Abstract Resilient Entity domain class with key type : {@link Long}<br>
 * All Entity domain's with Long primary key MUST extend {@link AbstractResilientLongIdEntity this}.
 * 
 * <p>
 * This is needed because the hibernate generated classes (mappings) can't infer the {@link #id} property type from a
 * Generic (my first solution). It was generated with type {@link Object}, which in turn, created a problem in the
 * {@link QueryService#buildRangeSpecification}.
 * </p>
 * 
 * @param <T> Entity Domain type class
 */
@MappedSuperclass
public abstract class AbstractResilientLongIdEntity<T extends AbstractResilientEntity<T, Long>>
    extends AbstractResilientEntity<T, Long> {
  private static final long serialVersionUID = 1L;

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

  @Override
  public Long getId() {
    return this.id;
  }

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

  @Override
  public void setId(Long id) {
    this.id = id;
  }

  // This is a safe cast, since its GUARANTEED that DOMAIN is always a subclass of  AbstractEntity
  @SuppressWarnings("unchecked")
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(Hibernate.getClass(o).isInstance(this))) {
      return false;
    }
    return getId() != null && getId().equals(((T) o).getId());
  }
}
