package com.oguerreiro.resilient.domain;

import java.util.ArrayList;
import java.util.List;

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

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.oguerreiro.resilient.domain.enumeration.DashboardComponentChartType;
import com.oguerreiro.resilient.domain.enumeration.DashboardComponentType;
import com.oguerreiro.resilient.domain.enumeration.DashboardComponentView;
import com.oguerreiro.resilient.security.custom.ResilientSecurityResourceConfig;

import jakarta.persistence.CascadeType;
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.OrderBy;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

/**
 * DashboardComponent
 * Defines a component for dashboard. Nothing more than a group of outputs (variables of output type)
 */
@Entity
@Table(name = "dashboard_component")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@ResilientSecurityResourceConfig()
public class DashboardComponent extends AbstractResilientLongIdEntity<DashboardComponent> {

  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;

  @Column(name = "description")
  private String description;

  @Column(name = "is_active")
  private Boolean isActive;

  @NotNull
  @Enumerated(EnumType.STRING)
  @Column(name = "type")
  private DashboardComponentType type;

  @NotNull
  @Enumerated(EnumType.STRING)
  @Column(name = "dashboard_view")
  private DashboardComponentView view;

  @Enumerated(EnumType.STRING)
  @Column(name = "chart_type")
  private DashboardComponentChartType chartType;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "dashboardComponent", cascade = CascadeType.ALL, orphanRemoval = true)
  @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
  @JsonIgnoreProperties(value = { "dashboardComponent" }, allowSetters = true)
  @OrderBy("indexOrder ASC")
  private List<DashboardComponentDetail> dashboardComponentDetails = new ArrayList<>();

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "dashboardComponent", cascade = CascadeType.ALL, orphanRemoval = true)
  @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
  @JsonIgnoreProperties(value = { "dashboardComponent" }, allowSetters = true)
  private List<DashboardComponentOrganization> dashboardComponentOrganizations = new ArrayList<>();

  @NotNull
  @Column(name = "is_exportable")
  private Boolean isExportable;

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

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

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

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

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

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

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

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

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

  public Boolean getIsActive() {
    return this.isActive;
  }

  public DashboardComponent isActive(Boolean isActive) {
    this.setIsActive(isActive);
    return this;
  }

  public void setIsActive(Boolean isActive) {
    this.isActive = isActive;
  }

  public DashboardComponentType getType() {
    return this.type;
  }

  public DashboardComponent type(DashboardComponentType type) {
    this.setType(type);
    return this;
  }

  public void setType(DashboardComponentType type) {
    this.type = type;
  }

  public DashboardComponentView getView() {
    return this.view;
  }

  public DashboardComponent view(DashboardComponentView view) {
    this.setView(view);
    return this;
  }

  public void setView(DashboardComponentView view) {
    this.view = view;
  }

  public DashboardComponentChartType getChartType() {
    return this.chartType;
  }

  public DashboardComponent chartType(DashboardComponentChartType chartType) {
    this.setChartType(chartType);
    return this;
  }

  public void setChartType(DashboardComponentChartType chartType) {
    this.chartType = chartType;
  }

  public List<DashboardComponentDetail> getDashboardComponentDetails() {
    return this.dashboardComponentDetails;
  }

  public void setDashboardComponentDetails(List<DashboardComponentDetail> dashboardComponentDetails) {
    if (this.dashboardComponentDetails != null) {
      this.dashboardComponentDetails.forEach((v) -> v.setDashboardComponent(null));
    }
    if (dashboardComponentDetails != null) {
      dashboardComponentDetails.forEach((v) -> v.setDashboardComponent(this));
    }
    this.dashboardComponentDetails = dashboardComponentDetails;
  }

  public DashboardComponent dashboardComponentDetails(List<DashboardComponentDetail> dashboardComponentDetails) {
    this.setDashboardComponentDetails(dashboardComponentDetails);
    return this;
  }

  public DashboardComponent addDashboardComponentDetail(DashboardComponentDetail dashboardComponentDetail) {
    this.dashboardComponentDetails.add(dashboardComponentDetail);
    dashboardComponentDetail.setDashboardComponent(this);
    return this;
  }

  public DashboardComponent removeDashboardComponentDetail(DashboardComponentDetail dashboardComponentDetail) {
    this.dashboardComponentDetails.remove(dashboardComponentDetail);
    dashboardComponentDetail.setDashboardComponent(null);
    return this;
  }

  public List<DashboardComponentOrganization> getDashboardComponentOrganizations() {
    return this.dashboardComponentOrganizations;
  }

  public void setDashboardComponentOrganizations(List<DashboardComponentOrganization> dashboardComponentOrganizations) {
    if (this.dashboardComponentOrganizations != null) {
      this.dashboardComponentOrganizations.forEach((v) -> v.setDashboardComponent(null));
    }
    if (dashboardComponentOrganizations != null) {
      dashboardComponentOrganizations.forEach((v) -> v.setDashboardComponent(this));
    }
    this.dashboardComponentOrganizations = dashboardComponentOrganizations;
  }

  public DashboardComponent dashboardComponentOrganizations(
      List<DashboardComponentOrganization> dashboardComponentOrganizations) {
    this.setDashboardComponentOrganizations(dashboardComponentOrganizations);
    return this;
  }

  public DashboardComponent addDashboardComponentOrganization(
      DashboardComponentOrganization dashboardComponentOrganization) {
    this.dashboardComponentOrganizations.add(dashboardComponentOrganization);
    dashboardComponentOrganization.setDashboardComponent(this);
    return this;
  }

  public DashboardComponent removeDashboardComponentOrganization(
      DashboardComponentOrganization dashboardComponentOrganization) {
    this.dashboardComponentOrganizations.remove(dashboardComponentOrganization);
    dashboardComponentOrganization.setDashboardComponent(null);
    return this;
  }

  public Boolean getIsExportable() {
    return isExportable;
  }

  public DashboardComponent isExportable(Boolean isExportable) {
    this.setIsExportable(isExportable);
    return this;
  }

  public void setIsExportable(Boolean isExportable) {
    this.isExportable = isExportable;
  }

  //@formatter:off
  @Override
  public String toString() {
    return "DashboardComponent{" + 
              "id=" + getId() + 
              ", code='" + getCode() + "'" + 
              ", name='" + getName() + "'" + 
              ", description='" + getDescription() + "'" +
              ", type='" + getType() + "'" +
              ", view='" + getView() + "'" +
              ", chartType='" + getChartType() + "'" +
              ", isExportable='" + getIsExportable() + "'" +
              ", isActive='" + getIsActive() + "'" +
              ", version=" + getVersion() + 
           "}";
  }
//@formatter:on
}
