package com.oguerreiro.resilient.domain;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.oguerreiro.resilient.domain.enumeration.UnitValueType;
import com.oguerreiro.resilient.security.custom.ResilientSecurityResourceConfig;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;

/**
 * UnitType
 * Type of measure unit types. Convertions can only be done within Unit's of the same UnitType
 */
@Entity
@Table(name = "unit_type")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@ResilientSecurityResourceConfig()
public class UnitType extends AbstractResilientLongIdEntity<UnitType> {

  private static final long serialVersionUID = 1L;

  @NotNull
  @Column(name = "name", nullable = false, unique = true)
  private String name;

  @NotNull
  @Column(name = "description", nullable = false)
  private String description;

  @NotNull
  @Enumerated(EnumType.STRING)
  @Column(name = "value_type", nullable = false)
  private UnitValueType valueType;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "unitType")
  @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
  @JsonIgnoreProperties(value = { "fromUnits", "toUnits", "baseUnits", "sourceUnits", "inputData", "outputData",
      "variableUnits", "unitType" }, allowSetters = true)
  private Set<Unit> units = new HashSet<>();

  public String getName() {
    return this.name;
  }

  public UnitType name(String name) {
    this.setName(name);
    return this;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return this.description;
  }

  public UnitType description(String description) {
    this.setDescription(description);
    return this;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public UnitValueType getValueType() {
    return this.valueType;
  }

  public UnitType valueType(UnitValueType valueType) {
    this.setValueType(valueType);
    return this;
  }

  public void setValueType(UnitValueType valueType) {
    this.valueType = valueType;
  }

  public Set<Unit> getUnits() {
    return this.units;
  }

  public void setUnits(Set<Unit> units) {
    if (this.units != null) {
      this.units.forEach(i -> i.setUnitType(null));
    }
    if (units != null) {
      units.forEach(i -> i.setUnitType(this));
    }
    this.units = units;
  }

  public UnitType units(Set<Unit> units) {
    this.setUnits(units);
    return this;
  }

  public UnitType addUnit(Unit unit) {
    this.units.add(unit);
    unit.setUnitType(this);
    return this;
  }

  public UnitType removeUnit(Unit unit) {
    this.units.remove(unit);
    unit.setUnitType(null);
    return this;
  }

  // prettier-ignore
  @Override
  public String toString() {
    return "UnitType{" + "id=" + getId() + ", name='" + getName() + "'" + ", description='" + getDescription() + "'"
        + ", valueType='" + getValueType() + "'" + ", version=" + getVersion() + "}";
  }
}
