package gov.va.vinci.dart.biz;

import gov.va.vinci.dart.common.exception.ObjectNotFoundException;
import gov.va.vinci.dart.service.DartObjectFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="DataSource",schema="hib")
public class DataSource extends ReferenceObject implements Comparable {

	@Column(name="domainname")
	private String domainName;
	
	@Column(name="infosite")
	private String infoSite;

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

	@ManyToMany(fetch=FetchType.LAZY)
	@JoinTable(
		      name="datasourcedocumenttemplate", schema="hib",
		      joinColumns={@JoinColumn(name="datasourceid", referencedColumnName="ID")},
		      inverseJoinColumns={@JoinColumn(name="documenttemplateid", referencedColumnName="ID")})
	Set<DocumentTemplate> documentTemplates;
	
	@ManyToMany(fetch=FetchType.LAZY)
	@JoinTable(
		      name="datasourceworkflowtemplate", schema="hib",
		      joinColumns={@JoinColumn(name="datasourceid", referencedColumnName="ID")},
		      inverseJoinColumns={@JoinColumn(name="workflowtemplateid", referencedColumnName="ID")})
	Set<WorkflowTemplate> workflowTemplates;
	
/* TODO: disable the data sources based on the request type *
	@ManyToMany(fetch=FetchType.LAZY)
	@JoinTable(
		      name="disableddatasource", schema="hib",
		      joinColumns={@JoinColumn(name="datasourceid", referencedColumnName="ID")},
    		  inverseJoinColumns={@JoinColumn(name="requesttypeid", referencedColumnName="requesttype")})
	Set<Request> requestsWithDisabledDataSources;
/* TODO: disable the data sources based on the request type */
	
	
	
	public static List<DataSource> listAll() {
		return  DartObjectFactory.getInstance().getDataSourceDAO().listAll();
	}

	public static DataSource findById(int dataSourceId) throws ObjectNotFoundException {
		return DartObjectFactory.getInstance().getDataSourceDAO().findById(dataSourceId);
	}

	public static List<DataSource> findByDocumentTemplateId(int documentTemplateId) {
		return DartObjectFactory.getInstance().getDataSourceDAO().findByDocumentTemplateId(documentTemplateId);
	}

	public static List<Integer> findDisabledIdByRequestType(final int requestTypeId) {
		return DartObjectFactory.getInstance().getDataSourceDAO().findDisabledIdByRequestType(requestTypeId);
	}
	
	public static List<DataSource> findByHeaderIdAndRequestType(final int dataSourceHeaderId, final int requestTypeId) {
		return DartObjectFactory.getInstance().getDataSourceDAO().findByHeaderIdAndRequestType(dataSourceHeaderId, requestTypeId);
	}

	
	public String getDomainName() {
		return domainName;
	}

	public void setDomainName(final String domainName) {
		this.domainName = domainName;
	}
	
	public String getInfoSite() {
		return infoSite;
	}

	public void setInfoSite(final String infoSite) {
		this.infoSite = infoSite;
	}
	
	public String getEvaluator() {
		return evaluator;
	}

	public void setEvaluator(final String evaluator) {
		this.evaluator = evaluator;
	}

	public Set<DocumentTemplate> getDocumentTemplates() {
		return documentTemplates;
	}
	
	public void setDocumentTemplates(final Set<DocumentTemplate> documentTemplates) {
		this.documentTemplates = documentTemplates;
	}

	public Set<WorkflowTemplate> getWorkflowTemplates() {
		return workflowTemplates;
	}

	
//	public hasIndependentWorkflowsOnly() {
//		boolean isIndependentOnly = false;
//		
//		Set<WorkflowTemplate> dataSourceWorkflowTemplates = ds.getWorkflowTemplates();
//		if( dataSourceWorkflowTemplates != null ) {
//			for( WorkflowTemplate workflowTemplate : dataSourceWorkflowTemplates ) {
//				if( workflowTemplate != null && workflowTemplate.getWorkflowTypeId() != WorkflowResolver.WF_INDEPENDENT ) {
//					isIndependentOnly = false;
//				}
//			}
//		}
//		
//		return isIndependentOnly;
//	}
//	
//	private Set<DocumentTemplate> getIndependentOnlyDocuments() {
//		Set<DocumentTemplate> independentOnlyDocs = new HashSet<DocumentTemplate>();		
//		Set<DocumentTemplate> independentDocTemplates = new HashSet<DocumentTemplate>();
//
//		List<WorkflowTemplate> independentWorkflows = WorkflowTemplate.listByWorkflowTypeId(WorkflowResolver.WF_INDEPENDENT);
//		if( independentWorkflows != null ) {
//
//			for( WorkflowTemplate workflowTemplate : independentWorkflows ) {
//				if( workflowTemplate != null ) {
//					
//					Set<DocumentTemplate> docTemplates = workflowTemplate.getDocumentTemplates();
//					if( docTemplates != null ) {
//						independentDocTemplates.addAll(docTemplates);
//					}//end if
//
//				}//end if
//			}//end for
//
//		}//end if
//		
//		if( independentDocTemplates != null && independentDocTemplates.size() > 0 ) {
//			for( DocumentTemplate docTemplate : independentDocTemplates ) {
//				if( docTemplate != null ) {
//					boolean hasNonIndependentWorkflow = false;
//
//					Set<WorkflowTemplate> workflowTemplates = docTemplate.getWorkflowTemplates();
//					if( workflowTemplates != null && workflowTemplates.size() > 0 ) {	//have at least one workflow mapped to this document
//						for( WorkflowTemplate currWorkflow : workflowTemplates ) {
//							if( currWorkflow != null ) {
//								if( currWorkflow.getWorkflowTypeId() != WorkflowResolver.WF_INDEPENDENT ) {	//found a non-Independent workflow
//									hasNonIndependentWorkflow = true;
//									break;
//								}//end if
//							}//end if
//						}//end if
//						
//						//only independent workflows mapped to this document template, so keep it
//						if( hasNonIndependentWorkflow == false ) {
//							independentOnlyDocs.add(docTemplate);
//						}//end if
//					}//end if -- workflowTemplates
//				}///end if -- docTemplate
//			}//end for
//		}//end if
//		
//		return independentOnlyDocs;
//	}
//
//
//	private Set<DataSource> getIndependentOnlyDataSources() {
//		Set<DataSource> independentOnlyDocs = new HashSet<DataSource>();		
//		Set<DataSource> independentDocTemplates = new HashSet<DataSource>();
//
//		List<WorkflowTemplate> independentWorkflows = WorkflowTemplate.listByWorkflowTypeId(WorkflowResolver.WF_INDEPENDENT);
//		if( independentWorkflows != null ) {
//
//			for( WorkflowTemplate workflowTemplate : independentWorkflows ) {
//				if( workflowTemplate != null ) {
//					
//					Set<DocumentTemplate> docTemplates = workflowTemplate.getDocumentTemplates();
//					if( docTemplates != null ) {
//						independentDocTemplates.addAll(docTemplates);
//					}//end if
//
//				}//end if
//			}//end for
//
//		}//end if
//		
//		if( independentDocTemplates != null && independentDocTemplates.size() > 0 ) {
//			for( DocumentTemplate docTemplate : independentDocTemplates ) {
//				if( docTemplate != null ) {
//					boolean hasNonIndependentWorkflow = false;
//
//					Set<WorkflowTemplate> workflowTemplates = docTemplate.getWorkflowTemplates();
//					if( workflowTemplates != null && workflowTemplates.size() > 0 ) {	//have at least one workflow mapped to this document
//						for( WorkflowTemplate currWorkflow : workflowTemplates ) {
//							if( currWorkflow != null ) {
//								if( currWorkflow.getWorkflowTypeId() != WorkflowResolver.WF_INDEPENDENT ) {	//found a non-Independent workflow
//									hasNonIndependentWorkflow = true;
//									break;
//								}//end if
//							}//end if
//						}//end if
//						
//						//only independent workflows mapped to this document template, so keep it
//						if( hasNonIndependentWorkflow == false ) {
//							independentOnlyDocs.add(docTemplate);
//						}//end if
//					}//end if -- workflowTemplates
//				}///end if -- docTemplate
//			}//end for
//		}//end if
//		
//		return independentOnlyDocs;
//	}
	
	
	//in both src1 and src2
	public static List<DataSource> intersect(final Collection<DataSource> src1, final Collection<DataSource> src2) {
		List<DataSource> result = new ArrayList<DataSource>();
	
		for (DataSource ds1 : src1) {
			for (DataSource ds2 : src2) {
				if (ds1.getId() == ds2.getId()) {
					result.add(ds1);
				}
			}
		}
		
		return result;
	}
	
	//src1 - src2: in src1, but NOT in src2
	public static List<DataSource> minus(final Collection<DataSource> src1, final Collection<DataSource> src2) {
		List<DataSource> result = new ArrayList<DataSource>();
				
		for (DataSource ds1 : src1) {
			if( src2.contains(ds1) == false ) {	//in src1, but NOT in src2
				result.add(ds1);
			}
		}
		
		return result;
	}


	@Override 
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		
		if ((obj instanceof DataSource) == false) {
			return false;
		}
		
		return this.getId() == ((DataSource)obj).getId();	//compare the id column for the DataSource
	}
	
	@Override
	public int compareTo(Object o) {
		if (o == null) {
			return -1;
		}
		if ((o instanceof DataSource) == false) {
			return -1;
		}
		
		DataSource obj2 = (DataSource)o;

		// sort by id column for the DataSource
		if (this.getId() == obj2.getId()) {
			return 0;
		}
		
		return this.getId() < obj2.getId() ? -1 : 1;
	}
	
}
