package org.gcube.portlets.user.speciesdiscovery.client.job.occurrence;

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

import org.gcube.portlets.user.speciesdiscovery.client.resources.Resources;
import org.gcube.portlets.user.speciesdiscovery.shared.JobOccurrencesModel;

import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Html;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
 *
 */
public class OccurrenceJobSpeciesPanel extends ContentPanel {  
	

	/**
	 * This is a singleton
	 */
	private static OccurrenceJobSpeciesPanel instance;
	private static ContentPanel cp;
	private ContentPanel vp;
	private static HashMap<String, OccurrenceJobSpeciesProgressBar> hashProgressBars;
	private static HashMap<String, Boolean> hashLoadCompletedNotify;
	private static HashMap<String, ContentPanel> hashTableContentPanels;
	private static String LASTOPERATION = "Last Operation: ";
	private Html lastOperation = new Html(LASTOPERATION);
	private LayoutContainer lc;
	private static String WINDOWTITLE = "Species Occurrence Jobs";
	private static final String FAILED = "failed";
	private static final String COMPLETED = "completed";
	private static final String LOADING = "loading";
	private static final String PENDING = "pending";
	private static final String OPERATIONONE = "none";
	private static final String SAVING = "saving";

	private OccurrenceGridJob gridJob;
	private EventBus eventBus;
	
	protected Window speciesJobWindow = new Window();
	
	public static synchronized OccurrenceJobSpeciesPanel getInstance(EventBus eventBus) {
		if (instance == null)
			instance = new OccurrenceJobSpeciesPanel(eventBus);
		return instance;
	}

	private OccurrenceJobSpeciesPanel(EventBus eventBus) {
		this.eventBus = eventBus;
		this.gridJob = new OccurrenceGridJob(eventBus);

		this.setHeaderVisible(false);
		this.setLayout(new FitLayout());
		createSpeciesJobWindow();
//		createToolBar();
	}
	
	private void createSpeciesJobWindow(){
		
		lc = new LayoutContainer();
		lc.setStyleAttribute("margin", "5px");
		cp = new ContentPanel();
		cp.setBodyBorder(true);
		cp.setStyleAttribute("padding", "5px");
		cp.setLayout(new FitLayout());
		
		cp.add(gridJob);
		
		cp.setHeight(550);
		cp.setHeaderVisible(false);
		hashProgressBars = new HashMap<String, OccurrenceJobSpeciesProgressBar>();
		hashTableContentPanels = new HashMap<String, ContentPanel>();
		hashLoadCompletedNotify = new HashMap<String, Boolean>();
		cp.setScrollMode(Scroll.AUTO);
		
		lastOperation.setHtml(LASTOPERATION + OPERATIONONE);
		
//		cp.add(vp);
		lc.add(lastOperation);
		lc.add(cp);
//		
		speciesJobWindow.setHeading(WINDOWTITLE);
		speciesJobWindow.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getBluePlace16px()));
		speciesJobWindow.setSize(1020, 600);
		speciesJobWindow.setResizable(true);
		speciesJobWindow.setScrollMode(Scroll.AUTOX);
		speciesJobWindow.add(lc);
	}
	
//	private void createToolBar(){
//		ToolBar toolbar = new ToolBar();
//		
//		Button btnJobs = new Button("Species Jobs");
//		btnJobs.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.getJob()));
//		
//		btnJobs.addSelectionListener(new SelectionListener<ButtonEvent>() {
//
//			@Override
//			public void componentSelected(ButtonEvent ce) {
//				
//				speciesJobWindow.show();
//			}
//			
//		});
//		toolbar.add(btnJobs);
//		this.setTopComponent(toolbar);
//	}
	
	/**
	 * 
	 * @param jobsModel
	 * @return true if almost one progress bar is ongoing
	 */
	public boolean addListJob(List<JobOccurrencesModel> jobsModel){
		
		boolean isLoading = false;
		
		for(final JobOccurrencesModel jobModel : jobsModel){
			
			isLoading = addJob(jobModel);
		}
		
		return isLoading;
		
	}
	
	
	public boolean addJob(final JobOccurrencesModel jobModel){
		
		boolean isLoading = false;
		
//		Log.trace("add job :" +jobModel);
		
		OccurrenceJobSpeciesProgressBar jobsBar = hashProgressBars.get(jobModel.getJobIdentifier());
		
		if(jobsBar!=null){ //is update

			OccurrenceWindowInfoJobsSpecies win = (OccurrenceWindowInfoJobsSpecies) jobsBar.getData("win");
			
			if(win!=null){
				win.updateDescription(jobModel);
				win.layout();
				jobsBar.setData("win", win);
			}
			
			//IF job is COMPLETED OR FAILED OR COMPLETED WITH ERROR, IS NOT UPDATE
			if(jobsBar.isCompleted()){
				//FOR DEBUG
//				Log.trace("jobsBar " +jobModel.getName() + " completed, return" );
				return true;
			}
		
			
			updateProgressBarView(jobsBar, jobModel);
			
			gridJob.updateStatus(jobModel, jobsBar);

		}
		else{ //create new grid item that contains new progress bar
			
			
			OccurrenceJobSpeciesProgressBar jobProgressBar = new OccurrenceJobSpeciesProgressBar(jobModel.getJobIdentifier(), jobModel.getDownloadState().toString());
			
			gridJob.addJobIntoGrid(jobModel, jobProgressBar);
			
			updateProgressBarView(jobProgressBar, jobModel);
			
//			hashTableContentPanels.put(jobModel.getIdentifier(), panelTable); //add contentPanel into hashTableContentPanels
			hashProgressBars.put(jobModel.getJobIdentifier(), jobProgressBar); //add progressBar into hashProgressBars
			hashLoadCompletedNotify.put(jobModel.getJobIdentifier(), false); //add false (at load completed event) into hashLoadCompletedNotify
		}

		gridJob.layout();
		cp.layout();

		return isLoading;
	}
	
	
	private boolean updateProgressBarView(OccurrenceJobSpeciesProgressBar jobsBar, JobOccurrencesModel jobModel){

			switch (jobModel.getDownloadState()) {
			
			case PENDING:{
				jobsBar.setProgressText(PENDING);
				break;
			}
			
			case SAVING:{
				lastOperation.setHtml(LASTOPERATION + jobModel.getJobName() + " saving");
				jobsBar.getElement().getStyle().setBorderColor("#7093DB");
//				jobsBar.progressStart();
				jobsBar.setProgressText(SAVING);
				break;
			}
	
			case COMPLETED:{
				
				lastOperation.setHtml(LASTOPERATION + jobModel.getJobName() + " completed");

				jobsBar.getElement().getStyle().setBorderColor("#000000");
//				jobsBar.progressStop();
				jobsBar.updateProgressWithoutPercentage(100);
				jobsBar.setCompleted(true);
				jobsBar.updateText(COMPLETED);

				break;
			}
	
			case ONGOING:{ 

				if(jobModel.getPercentage()<100)
					jobsBar.setProgressText(LOADING);
				else
					jobsBar.setProgressText(SAVING);
				
				jobsBar.updateProgressWithPercentage(jobModel.getPercentage());
					
//				jobsBar.progressStart();

				return true;
			}
			
			case SAVED:{
				
				lastOperation.setHtml(LASTOPERATION + jobModel.getJobName() + " saved");
				
				jobsBar.getElement().getStyle().setBorderColor("#000000");
//				jobsBar.progressStop();
				jobsBar.updateProgressWithoutPercentage(100);
//				jobsBar.updateProgressWithPercentage(jobModel.getPercentage(), jobModel.getDownloadState().toString());
				jobsBar.setCompleted(true);
				jobsBar.updateText(COMPLETED);

				break;
			}
				
			case ONGOINGWITHFAILURES: {
				
				jobsBar.getElement().getStyle().setBorderColor("#f00");
				jobsBar.updateText("loading " + jobModel.getJobName() + " with failures");
				
				break;
			}
	
			case FAILED:{ 					
	
				jobsBar.getElement().getStyle().setBorderColor("#f00");
//				jobsBar.progressStop();
				jobsBar.setProgressText(FAILED);
				jobsBar.updateProgressWithPercentage(jobModel.getPercentage());
				jobsBar.setCompleted(true);
				jobsBar.updateText(FAILED);
		
				break;
			}
				
			case COMPLETEDWITHFAILURES:{
	
				jobsBar.getElement().getStyle().setBorderColor("#f00");
				jobsBar.updateText("loading " + jobModel.getJobName() + " with failures");
				jobsBar.updateProgressWithoutPercentage(100);
				jobsBar.setCompleted(true);
				
				break;
			}
		}
			
		return false;
		
	}

	public void removeSpeciesJob(String hashHPKey) {
		
	
		ContentPanel cp = hashTableContentPanels.get(hashHPKey);
		
		vp.remove(cp);
		lastOperation.setHtml(LASTOPERATION + cp.getId() + " deleted");
		hashProgressBars.remove(hashHPKey); //remove progress bar from hash
		hashTableContentPanels.remove(hashHPKey); //remove hp from hash 
		hashLoadCompletedNotify.remove(hashHPKey); //remove notify event

		vp.layout();
		
	}
	
	@SuppressWarnings("unused")
	private void deleteProgressCompleted(List<String> progressIdFound){
		
		List<String> progressIdNotFound = new ArrayList<String>();
		
		for(String key : hashTableContentPanels.keySet()){
			
//		    System.out.println("Key " + key );
			
			if(!progressIdFound.contains(key)){ //if key isn't not found - progress is completed so is removed
				
//				System.out.println("Key is not present " + key );
				 
				OccurrenceJobSpeciesProgressBar bulkPB = hashProgressBars.get(key);
				lastOperation.setHtml(LASTOPERATION + bulkPB.getProgressText() + " uploading completed");
				
//				bulkPB.updateProgress(100);
				progressIdNotFound.add(key);
			}
		}
		
		for(String key : progressIdNotFound){
			
			OccurrenceJobSpeciesProgressBar bulkPB = hashProgressBars.get(key);
			lastOperation.setHtml(LASTOPERATION + bulkPB.getProgressText() + " uploading completed");
			
//			vp.remove(hashHorizontalPanels.get(key)); //remove hp from view
			hashProgressBars.remove(key); //remove progress bar from hash
			hashTableContentPanels.remove(key); //remove hp from hash 
		}
		
		vp.layout();
		cp.layout();
	}

	public Window getSpeciesJobWindow() {
		return speciesJobWindow;
	}
	
	public void resetStructures(){
		
		this.gridJob.resetStore();
		
		hashProgressBars.clear();
		lastOperation.setHtml(LASTOPERATION);
		hashTableContentPanels.clear();
		hashLoadCompletedNotify.clear(); 
	}

	public OccurrenceGridJob getGridJob() {
		return gridJob;
	}
	

}

