package org.gcube.portlets.user.speciesdiscovery.shared.cluster;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.gcube.portlets.user.speciesdiscovery.shared.SearchResult;
import org.gcube.portlets.user.speciesdiscovery.shared.TaxonomyRow;
import org.gcube.portlets.user.speciesdiscovery.shared.util.NormalizeString;

/**
 * 
 * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
 *
 */
public class ClusterStructuresForTaxonomyRow implements Serializable{
	
	private static final String DATA_SOURCE_NOT_FOUND = "Data Source not found";

	/**
	 * 
	 */
	private static final long serialVersionUID = 2680552140187511057L;
	
	private Map<String, TaxonomyRow> hashResult = new HashMap<String, TaxonomyRow>();
	private HashMap<String,ClusterCommonNameDataSource<TaxonomyRow>> hashClusterCommonNamesDataSources = new HashMap<String,ClusterCommonNameDataSource<TaxonomyRow>>();
	private HashMap<String, ArrayList<String>> hashClusterScientificNameTaxonomyRowID = new HashMap<String, ArrayList<String>>(); //HASH scientific name - taxonomy row ID
	private ArrayList<String> listFoundDataSources = new ArrayList<String>();
	private ArrayList<String> listTaxonomyRowID;

	private boolean isReduced;

	private int totalRow;

	public ClusterStructuresForTaxonomyRow(){
		
	}
	
	public ClusterStructuresForTaxonomyRow(SearchResult<TaxonomyRow> result, boolean isReduced, int totalRow) {
		//Create hashMap row ID - resultRow
		for (TaxonomyRow row : result.getResults()) {
			hashResult.put(row.getIdToString(), row);
			
//			int parentsSize = row.getParents().size();
//			
//			//FILL LIST PARENT FOR PARENTS ITEM
//			for(int i=parentsSize-1; i>=0; i--){
//				TaxonomyRow taxon = row.getParents().get(i);
//				List<TaxonomyRow> sublistParents = new ArrayList<TaxonomyRow>();
////				for (TaxonomyRow taxon : taxonomy.getParents()) {
//				
//				if(i+1!=parentsSize)
//					sublistParents.addAll(row.getParents().subList(i+1, parentsSize));
//				
//				taxon.setParent(sublistParents);
//				
//////				DEBUG
////				System.out.println("parent of "+taxon.getName());
////				for (TaxonomyRow tax : sublistParents) {
////					System.out.println("taxon.getName() " + tax.getName());
////				}
////				System.out.println("\n\n");
//			}
			
			//DEBUG
//			System.out.println("principal "+row.getName() + " id " + row.getServiceId()+" parents");
//			for (TaxonomyRow tax : row.getParents()) {
//				System.out.println("taxon.getName() " + tax.getName());
//				System.out.println("parent of "+tax.getName());
//				for (TaxonomyRow taxon : tax.getParents()) {
//					System.out.println("taxon.getName() " + taxon.getName());
//				}
//				System.out.println("\n\n");
//			}
		}
		
		this.isReduced = isReduced;
		this.totalRow = totalRow;
		
		createStructures(result.getResults());
		createStructuresForCommonName();
	}
	
	public void createStructures(ArrayList<TaxonomyRow> arrayListTax){

		if(arrayListTax.size()>0){

			for (TaxonomyRow row : arrayListTax) {

				String dataSource = row.getDataProviderName();
				
				if(dataSource==null || dataSource.isEmpty())
					dataSource = DATA_SOURCE_NOT_FOUND;

				String keyScientificName = row.getName();
				
				if(keyScientificName== null || keyScientificName.isEmpty())
					keyScientificName = "Undefined";
				else
					keyScientificName = NormalizeString.lowerCaseUpFirstChar(keyScientificName);
				
				if(hashClusterScientificNameTaxonomyRowID.get(keyScientificName)==null){

					listTaxonomyRowID = new ArrayList<String>(); //USED FOR CLUSTER COMMON NAMES
						
				}
				else{

					listTaxonomyRowID = hashClusterScientificNameTaxonomyRowID.get(keyScientificName); //USED FOR CLUSTER COMMON NAMES
				}

				if(listFoundDataSources.indexOf(dataSource)==-1)
					listFoundDataSources.add(dataSource);

				listTaxonomyRowID.add(row.getIdToString());
				hashClusterScientificNameTaxonomyRowID.put(keyScientificName, listTaxonomyRowID);

			}
		}
		
	}
	
	
	public void createStructuresForCommonName(){

		if(hashClusterScientificNameTaxonomyRowID.size()>0){

			for(String scientificName : hashClusterScientificNameTaxonomyRowID.keySet()){
				
				ArrayList<String> listTaxonomyRowID = hashClusterScientificNameTaxonomyRowID.get(scientificName);
				
				ClusterCommonNameDataSource<TaxonomyRow> cluster = new ClusterCommonNameDataSource<TaxonomyRow>(); //NEW CLUSTER

				for(int i=0; i<listTaxonomyRowID.size(); i++){
					TaxonomyRow row = hashResult.get(listTaxonomyRowID.get(i));
					cluster.updateHashCommonNamesDataSources(row);
				}
				
				hashClusterCommonNamesDataSources.put(scientificName, cluster);
		
			}
		}
		
	}


	public ArrayList<String> getListFoundDataSources() {
		return listFoundDataSources;
	}

	public HashMap<String, ArrayList<String>> getHashClusterScientificNameTaxonomyRowID() {
		return hashClusterScientificNameTaxonomyRowID;
	}

	public HashMap<String, ClusterCommonNameDataSource<TaxonomyRow>> getHashClusterCommonNamesDataSources() {
		return hashClusterCommonNamesDataSources;
	}

	public ArrayList<TaxonomyRow> getResult() {
		return new ArrayList<TaxonomyRow>(hashResult.values());
	}
	
	public TaxonomyRow getTaxonomyRowByKey(String key) {
		return hashResult.get(key);
	}

	public boolean isReduced() {
		return isReduced;
	}

	public void setReduced(boolean isReduced) {
		this.isReduced = isReduced;
	}

	public int getTotalRow() {
		return totalRow;
	}

	public void setTotalRow(int totalRow) {
		this.totalRow = totalRow;
	}

}
