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.security.custom.ResilientSecurityResourceConfig;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

/**
 * VariableClassType
 * Type of a list of Variable Classe's
 */
@Entity
@Table(name = "variable_class_type")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@ResilientSecurityResourceConfig()
public class VariableClassType extends AbstractResilientLongIdEntity<VariableClassType> {
  private static final long serialVersionUID = 1L;

  /**
   * User defined code. Must be unique
   */
  @NotNull
  @Size(min = 1)
  @Column(name = "code", nullable = false, unique = true)
  private String code;

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

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

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

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "variableClassType", cascade = CascadeType.ALL, orphanRemoval = true)
  @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
  @JsonIgnoreProperties(value = { "variableClassType" }, allowSetters = true)
  private Set<VariableClass> variableClasses = new HashSet<>();

  public String getCode() {
    return this.code;
  }

  public VariableClassType code(String code) {
    this.setCode(code);
    return this;
  }

  public void setCode(String code) {
    this.code = code;
  }

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

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

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

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

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

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

  public String getLabel() {
    return this.label;
  }

  public VariableClassType label(String label) {
    this.setLabel(label);
    return this;
  }

  public void setLabel(String label) {
    this.label = label;
  }

  public Set<VariableClass> getVariableClasses() {
    return this.variableClasses;
  }

  public void setVariableClasses(Set<VariableClass> variableClasses) {
    if (this.variableClasses != null) {
      this.variableClasses.forEach((v) -> v.setVariableClassType(null));
    }
    if (variableClasses != null) {
      variableClasses.forEach((v) -> v.setVariableClassType(this));
    }
    this.variableClasses = variableClasses;
  }

  public VariableClassType variableClasses(Set<VariableClass> variableClasses) {
    this.setVariableClasses(variableClasses);
    return this;
  }

  public VariableClassType addVariableClass(VariableClass variableClass) {
    this.variableClasses.add(variableClass);
    variableClass.setVariableClassType(this);
    return this;
  }

  public VariableClassType removeVariableClass(VariableClass variableClass) {
    this.variableClasses.remove(variableClass);
    variableClass.setVariableClassType(null);
    return this;
  }

//@formatter:off
  @Override
  public String toString() {
    return "VariableClassType{" + 
              "id=" + getId() + 
              ", code='" + getCode() + "'" + 
              ", name='" + getName() + "'" + 
              ", description='" + getDescription() + "'" + 
              ", label='" + getLabel() + "'" + 
              ", version=" + getVersion()
        + "}";
  }
//@formatter:on
}
