package eu.dnetlib.enabling.datasources.common;

import java.sql.Timestamp;
import java.util.Objects;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Sets;
import com.google.gson.Gson;

/**
 * Api
 */
@MappedSuperclass
public class Api<AP extends ApiParam> implements Comparable<Api<AP>> {

	@Id
	protected String id = null;
	protected String protocol = null;
	protected String datasource = null;
	protected String contentdescription = null;
	protected Boolean active = false;
	protected Boolean removable = true;
	protected String typology = null;
	protected String compatibility;

	@Transient
	protected boolean compatibilityOverrided = false;

	@Column(name = "metadata_identifier_path")
	protected String metadataIdentifierPath;

	@Column(name = "last_collection_total")
	protected Integer lastCollectionTotal;

	@Column(name = "last_collection_date")
	protected Timestamp lastCollectionDate;

	@Column(name = "last_collection_mdid")
	protected String lastCollectionMdid;

	@Column(name = "last_aggregation_total")
	protected Integer lastAggregationTotal;

	@Column(name = "last_aggregation_date")
	protected Timestamp lastAggregationDate;

	@Column(name = "last_aggregation_mdid")
	protected String lastAggregationMdid;

	@Column(name = "last_download_total")
	protected Integer lastDownloadTotal;

	@Column(name = "last_download_date")
	protected Timestamp lastDownloadDate;

	@Column(name = "last_download_objid")
	protected String lastDownloadObjid;

	@Column(name = "last_validation_job")
	protected String lastValidationJob;
	protected String baseurl = null;

	@OneToMany(mappedBy = "id.api", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	protected Set<AP> apiParams = Sets.newHashSet();

	public Api() {}

	public String getId() {
		return id;
	}

	public String getProtocol() {
		return protocol;
	}

	public String getDatasource() {
		return datasource;
	}

	public String getContentdescription() {
		return contentdescription;
	}

	public Boolean getActive() {
		return active;
	}

	public Boolean getRemovable() {
		return removable;
	}

	public String getTypology() {
		return typology;
	}

	public String getCompatibility() {
		return compatibility;
	}

	public boolean isCompatibilityOverrided() {
		return compatibilityOverrided;
	}

	public String getMetadataIdentifierPath() {
		return metadataIdentifierPath;
	}

	public Integer getLastCollectionTotal() {
		return lastCollectionTotal;
	}

	public Timestamp getLastCollectionDate() {
		return lastCollectionDate;
	}

	public String getLastCollectionMdid() {
		return lastCollectionMdid;
	}

	public Integer getLastAggregationTotal() {
		return lastAggregationTotal;
	}

	public Timestamp getLastAggregationDate() {
		return lastAggregationDate;
	}

	public String getLastAggregationMdid() {
		return lastAggregationMdid;
	}

	public Integer getLastDownloadTotal() {
		return lastDownloadTotal;
	}

	public Timestamp getLastDownloadDate() {
		return lastDownloadDate;
	}

	public String getLastDownloadObjid() {
		return lastDownloadObjid;
	}

	public String getLastValidationJob() {
		return lastValidationJob;
	}

	public String getBaseurl() {
		return baseurl;
	}

	public Set<AP> getApiParams() {
		return apiParams;
	}

	public Api<AP> setId(final String id) {
		this.id = id;
		return this;
	}

	public Api<AP> setProtocol(final String protocol) {
		this.protocol = protocol;
		return this;
	}

	public Api<AP> setDatasource(final String datasource) {
		this.datasource = datasource;
		return this;
	}

	public Api<AP> setContentdescription(final String contentdescription) {
		this.contentdescription = contentdescription;
		return this;
	}

	public Api<AP> setActive(final Boolean active) {
		this.active = active;
		return this;
	}

	public Api<AP> setRemovable(final Boolean removable) {
		this.removable = removable;
		return this;
	}

	public Api<AP> setTypology(final String typology) {
		this.typology = typology;
		return this;
	}

	public Api<AP> setCompatibility(final String compatibility) {
		this.compatibility = compatibility;
		return this;
	}

	public Api<AP> setCompatibilityOverrided(final boolean compatibilityOverrided) {
		this.compatibilityOverrided = compatibilityOverrided;
		return this;
	}

	public Api<AP> setMetadataIdentifierPath(final String metadataIdentifierPath) {
		this.metadataIdentifierPath = metadataIdentifierPath;
		return this;
	}

	public Api<AP> setLastCollectionTotal(final Integer lastCollectionTotal) {
		this.lastCollectionTotal = lastCollectionTotal;
		return this;
	}

	public Api<AP> setLastCollectionDate(final Timestamp lastCollectionDate) {
		this.lastCollectionDate = lastCollectionDate;
		return this;
	}

	public Api<AP> setLastCollectionMdid(final String lastCollectionMdid) {
		this.lastCollectionMdid = lastCollectionMdid;
		return this;
	}

	public Api<AP> setLastAggregationTotal(final Integer lastAggregationTotal) {
		this.lastAggregationTotal = lastAggregationTotal;
		return this;
	}

	public Api<AP> setLastAggregationDate(final Timestamp lastAggregationDate) {
		this.lastAggregationDate = lastAggregationDate;
		return this;
	}

	public Api<AP> setLastAggregationMdid(final String lastAggregationMdid) {
		this.lastAggregationMdid = lastAggregationMdid;
		return this;
	}

	public Api<AP> setLastDownloadTotal(final Integer lastDownloadTotal) {
		this.lastDownloadTotal = lastDownloadTotal;
		return this;
	}

	public Api<AP> setLastDownloadDate(final Timestamp lastDownloadDate) {
		this.lastDownloadDate = lastDownloadDate;
		return this;
	}

	public Api<AP> setLastDownloadObjid(final String lastDownloadObjid) {
		this.lastDownloadObjid = lastDownloadObjid;
		return this;
	}

	public Api<AP> setLastValidationJob(final String lastValidationJob) {
		this.lastValidationJob = lastValidationJob;
		return this;
	}

	public Api<AP> setBaseurl(final String baseurl) {
		this.baseurl = baseurl;
		return this;
	}

	public Api<AP> setApiParams(final Set<AP> apiParams) {
		this.apiParams = apiParams;
		return this;
	}

	@Override
	public boolean equals(final Object o) {
		if (this == o) { return true; }
		if (o == null || getClass() != o.getClass()) { return false; }
		final Api<?> api = (Api<?>) o;
		return Objects.equals(this.id, api.id);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see eu.dnetlib.openaire.exporter.model.datasource.db.ApiInterface#hashCode()
	 */

	@Override
	public int hashCode() {
		return Objects.hash(id);
	}

	@Override
	public String toString() {
		return new Gson().toJson(this);
	}

	@Override
	public int compareTo(final Api<AP> a) {
		return ComparisonChain.start()
				.compare(getId(), a.getId())
				.result();
	}

}
