/******************************************************************************
 * 
 * Copyright (c) 2007 Sakai Project/Sakai Foundation
 * Licensed under the Educational Community License version 1.0
 * 
 * A copy of the Educational Community License has been included in this 
 * distribution and is available at: http://www.opensource.org/licenses/ecl1.php
 * 
 *****************************************************************************/

package org.sakaiproject.wontovlab.tool.jsf;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIData;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import org.sakaiproject.wontovlab.logic.AccessControlLogic;
import org.sakaiproject.wontovlab.logic.ExperimentLogic;
import org.sakaiproject.wontovlab.logic.ExternalLogic;
import org.sakaiproject.wontovlab.model.AccessControl;
import org.sakaiproject.wontovlab.model.Experiment;
import org.wontovlab.tool.WPF;


/**
 * This is a backing bean for the JSF app which handles the events and
 * sends the information from the logic layer to the UI
 * @author Sakai App Builder -AZ
 */
public class ExperimentBean 
{

	private static Log log = LogFactory.getLog(ExperimentBean.class);
	
	public Locale locale = new Locale("pt", "BR");
	private ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
	
	private ExternalLogic externalLogic;
	
	private static final String EXPERIMENT_DEFAULT_NAME = "";
	private static final String EXPERIMENT_DEFAULT_DESCRIPTION = "";
	private static final UploadedFile EXPERIMENT_DEFAULT_IMAGE = null;
	private static final String EXPERIMENT_DEFAULT_IMAGE_NAME = null;

	public WPF wpf;
	
	private boolean hasStepsCreated = false;
	
	private UIData dataTable;
	
	private DataModel listExperiments;
	
	private ExperimentWrapper currentExperiment;

	private int firstScoreRow;
	
	private AccessControlLogic accessControlLogic;

	private ExperimentLogic experimentLogic;
	
	
	
	private String experimentName = EXPERIMENT_DEFAULT_NAME;
	private String experimentDescription = EXPERIMENT_DEFAULT_DESCRIPTION;
	private UploadedFile experimentImage = EXPERIMENT_DEFAULT_IMAGE;
	private String imageName = EXPERIMENT_DEFAULT_IMAGE_NAME;


	
	
	
	////////////////
	private org.wontovlab.model.Experiment wontovlabCurrentExperiment = null;
	private String protocol = null;
	////////////////
	
	
	
	
	
	public org.wontovlab.model.Experiment getWontovlabCurrentExperiment() {
		return wontovlabCurrentExperiment;
	}

	public String getProtocol() {
		return protocol;
	}

	public void setWontovlabCurrentExperiment(
			org.wontovlab.model.Experiment wontovlabCurrentExperiment) {
		this.wontovlabCurrentExperiment = wontovlabCurrentExperiment;
	}
	
	public AccessControl accessControl; //instanciada uma vez, para persistir log no banco - usuario e hora de login



	public AccessControlLogic getAccessControlLogic() {
		return accessControlLogic;
	}
	public void setAccessControlLogic(AccessControlLogic accessControlLogic) {
		this.accessControlLogic = accessControlLogic;
	}

	public UIData getDataTable()
	{
		return dataTable;
	}
	public void setDataTable(UIData dataTable)
	{
		this.dataTable = dataTable;
	}

	public ExperimentWrapper getCurrentExperiment()
	{
		return currentExperiment;
	}
	public void setCurrentExperiment(ExperimentWrapper currentExperiment)
	{
		this.currentExperiment = currentExperiment;
	}

	public String getexperimentName()
	{
		return experimentName;
	}
	public void setexperimentName(String experimentName)
	{
		this.experimentName = experimentName;
	}

	public String getexperimentDescription()
	{
		return experimentDescription;
	}
	public void setexperimentDescription(String experimentDescription)
	{
		this.experimentDescription = experimentDescription;
	}
	
	
	public UploadedFile getExperimentImage()
	{
		return experimentImage;
	}
	public void setExperimentImage(UploadedFile experimentImage)
	{
		this.experimentImage = experimentImage;
	}
	
	public String getImageName()
	{
		return imageName;
	}
	public void setImageName(String imageName)
	{
		this.imageName = imageName;
	}

	public ExperimentLogic getExperimentLogic()
	{
		return experimentLogic;
	}
	public void setExperimentLogic(ExperimentLogic experimentLogic)
	{
		this.experimentLogic = experimentLogic;
	}

	public ExternalLogic getExternalLogic() {
		return externalLogic;
	}
	public void setExternalLogic(ExternalLogic externalLogic) {
		this.externalLogic = externalLogic;
	}

	public WPF getWpf() {
		return wpf;
	}
	public void setWpf(WPF wpf) {
		this.wpf = wpf;
	}

	
	
	
	public ExperimentBean() 
	{
		//TO SEE setInit() method which is called before the constructor
	}
	
	public void setInit(boolean x) {
		//IF YOU WANT TO USE AN ONTOLOGY THAT IS AVAILABLE IN A URL, YOU CAN USE THIS:
		//wpf = new WPF(false, "http://www.dc.ufscar.br/~daniel_cugler/DomainOntology.owl", "http://www.owl-ontologies.com/Ontology1251833905.owl",
		    	//"http://www.dc.ufscar.br/~daniel_cugler/ApplicationOntology.owl", "http://www.owl-ontologies.com/Ontology1258201595.owl");
		
		wpf = new WPF(true, externalLogic.getSakaiHomePath() + "DomainOntology.owl", "http://www.owl-ontologies.com/Ontology1251833905.owl",
				externalLogic.getSakaiHomePath() + "ApplicationOntology.owl", "http://www.owl-ontologies.com/Ontology1258201595.owl");
		
	}
	

	public boolean getCanCreate()
	{
		return experimentLogic.canCreateExperiments(externalLogic.getCurrentLocationId(), externalLogic.getCurrentUserId());
	}
	
	public boolean isImageAvailable()
	{
		if (experimentLogic.getExperimentImageName(currentExperiment.getExperiment()) != null)
		{
			return true;
		}
		
		return false;
	}
	
	
	public String getCurrentUserDisplayName() {
		return externalLogic.getUserDisplayName(externalLogic.getCurrentUserId());
	}

	
	public String processActionAdd()
	{
		log.debug("in process action add...");
		FacesContext fc = FacesContext.getCurrentInstance();
		// Test for empty items and don't add them
		if (experimentName != null && !experimentName.trim().equals("")
			&& experimentDescription != null && !experimentDescription.trim().equals("")) {
			String message;
			Experiment experiment;
			
			
			if (currentExperiment == null) 
			{
				experiment = new Experiment();
				// ownerId, locationId, and dateCreated are set in the logic.saveItem
				message = bundle.getString("new_weblab_add_success") + " " + experimentName;
			} 
			else 
			{
				experiment = currentExperiment.getExperiment();
				message = bundle.getString("edit_weblab_success") + " " + experimentName;
			}
			
			experiment.setName(experimentName);
			experiment.setDescription(experimentDescription);
			
			
			experiment.setOwnerId(externalLogic.getCurrentUserId());
			

			experimentLogic.saveExperiment(experiment);
			
			
			
			//Writing image
			
			if (experimentImage != null)
			{
				
				if (currentExperiment != null)
				{
					//Should delete the current photo if it is an update
					experimentLogic.deleteExperimentImage(experiment.getExperimentId());
				}
				
														
				try
				{
					experimentLogic.saveExperimentImage(experiment, experimentImage.getName(), experimentImage.getInputStream());
					fc.addMessage("weblabs", new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
				} 
				catch (IOException e)
				{
					fc.addMessage("weblabs", new FacesMessage(FacesMessage.SEVERITY_ERROR, bundle.getString("new_weblab_image_save_failure"), bundle.getString("new_weblab_image_save_failure") + " " + e.getMessage()));
					e.printStackTrace();
				}
			}
			else
			{
				fc.addMessage("weblabs", new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
			}
				
			// Reset text
			experimentName = EXPERIMENT_DEFAULT_NAME;
			experimentDescription = EXPERIMENT_DEFAULT_DESCRIPTION;
			experimentImage = EXPERIMENT_DEFAULT_IMAGE;
			
		} 
		else 
		{
			String message;
			if (experimentName == null || experimentName.trim().equals(""))
			{
				message = bundle.getString("new_weblab_add_failure_empty_name");
				fc.addMessage("weblabs", new FacesMessage(FacesMessage.SEVERITY_WARN, message, message));
			}
			
			if (experimentDescription == null || experimentDescription.trim().equals(""))
			{
				message = bundle.getString("new_weblab_add_failure_empty_description");
				fc.addMessage("weblabs", new FacesMessage(FacesMessage.SEVERITY_WARN, message, message));
			}
			
			
		}
		return "addedExperiment";
	}

	public String processActionDelete() 
	{
		log.debug("in process action delete...");
		currentExperiment = (ExperimentWrapper) dataTable.getRowData(); // gets the user selected item
		String experimentName = currentExperiment.getExperiment().getName();
		FacesContext fc = FacesContext.getCurrentInstance();
		
		long experimentId = currentExperiment.getExperiment().getExperimentId();
		
		try {
			experimentLogic.removeExperiment(currentExperiment.getExperiment());
			
			if (!experimentLogic.deleteExperimentImage(experimentId))
			{
				fc.addMessage("weblabs", new FacesMessage(FacesMessage.SEVERITY_INFO, bundle.getString("remove_weblab_success") + " " + experimentName, bundle.getString("remove_weblab_success") + " " + experimentName));
			}
			
			String message = bundle.getString("remove_weblab_success") + " " + experimentName;
			fc.addMessage("weblabs", new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
			
			currentExperiment = null;
			
		} catch (Exception e) {
			String message = experimentName + " não pode ser removido. Há itens cadastrados para este experimento.";
			fc.addMessage("weblabs", new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
			// TODO: handle exception
		}
		
		return "deleteExperiment";
	}

	public String processActionNew() 
	{
		log.debug("in process action new weblab...");
		currentExperiment = null;
		
		// set the values to the new defaults
		experimentName = EXPERIMENT_DEFAULT_NAME;
		experimentDescription = EXPERIMENT_DEFAULT_DESCRIPTION;
		
		
		
		return "newExperiment";
	}

	public String processActionUpdate() 
	{
		
		log.debug("in process action update...");
		currentExperiment = (ExperimentWrapper) dataTable.getRowData(); // gets the user selected item
		
		// set the values to those of the selected item
		experimentName = currentExperiment.getExperiment().getName();
		experimentDescription = currentExperiment.getExperiment().getDescription();

		return "updateExperiment";

	}

	public String processActionList() 
	{
		log.debug("in process action list weblabs...");

		return "listExperiment";
	}
	
	public String processActionDetail() 
	{
		log.debug("in process detailing weblab...");
		currentExperiment = (ExperimentWrapper) dataTable.getRowData();
		
		// set the values to those of the selected item
		experimentName = currentExperiment.getExperiment().getName();
		experimentDescription = currentExperiment.getExperiment().getDescription();
		
		//Verifying if there is a image related to this weblab
		imageName = experimentLogic.getExperimentImageName(currentExperiment.getExperiment());
		
		processActionListProtocol(); //loading the protocol variable
		
		return "detailExperiment";
	}
	
	public String processActionBackDetail() 
	{
		log.debug("in process back detailing weblab...");
		
		// set the values to those of the selected item
		experimentName = currentExperiment.getExperiment().getName();
		experimentDescription = currentExperiment.getExperiment().getDescription();
		
		//Verifying if there is a image related to this weblab
		imageName = experimentLogic.getExperimentImageName(currentExperiment.getExperiment());
		
		return "detailExperiment";
	}
	
    public DataModel getListExperiments() 
    {
    	log.debug("wrapping weblabs for JSF datatable...");
		
		listExperiments = new ListDataModel(retrieveListWebLabs());
				
		return listExperiments;
    }
    
    private List retrieveListWebLabs()
    {
    	
////////////////////////////////////////////////////////////// Toda vez que entra na pagina principal, adiciona um log no banco do usuario, data e hora - singleton
    	Calendar data = Calendar.getInstance(); 
		if (accessControl == null) {
			accessControl = new AccessControl();
			accessControl.setOwnerId(externalLogic.getCurrentUserId());
			accessControl.setDate(data.getTime().toString());
			
			accessControlLogic.saveAccessControl(accessControl);
		}
//////////////////////////////////////////////////////////////		
    	
		
		
		
    	List<ExperimentWrapper> wrappedLabs = new ArrayList<ExperimentWrapper>();
		List labs = experimentLogic.listExperiments(externalLogic.getCurrentLocationId(), externalLogic.getCurrentUserId());
		
		for (Iterator iter = labs.iterator(); iter.hasNext(); ) 
		{
			ExperimentWrapper wrapper = new ExperimentWrapper((Experiment) iter.next());
			// Mark the item if the current user owns it and can delete it
			if( experimentLogic.canEditExperiment(wrapper.getExperiment(), externalLogic.getCurrentLocationId(), externalLogic.getCurrentUserId()) ) 
			{
				wrapper.setCanEdit(true);
			} 
			else 
			{
				wrapper.setCanEdit(false);
			}
			
			if( experimentLogic.canDeleteExperiment(wrapper.getExperiment(), externalLogic.getCurrentLocationId(), externalLogic.getCurrentUserId()) ) 
			{
				wrapper.setCanDelete(true);
			} 
			else 
			{
				wrapper.setCanDelete(false);
			}
			
			
			wrappedLabs.add(wrapper);
		}
		Collections.sort(wrappedLabs, new Comparator<ExperimentWrapper>()
		{
			public int compare(ExperimentWrapper w1, ExperimentWrapper w2)
			{
				return w1.getExperiment().getName().compareTo(w2.getExperiment().getName());
			}
		});
		
		return wrappedLabs;
    }
    
/*    public boolean isListEmpty()
    {
    	if (listExperiments == null)
    	{
    		listExperiments = new ListDataModel(retrieveListWebLabs());
    	}
    	
    	System.out.println("isListEmpty");
    	if (listExperiments == null){
    		System.out.println("NULL");
    		return true;
    	} else
    		System.out.println("Size: " + listExperiments.getRowCount());
    	
    	if (listExperiments.getRowCount() == 0)
    		return true;
    	
    	System.out.println("Vai retornar FALSE");
    	return false;
    	
    	//return (listExperiments == null || listExperiments.getRowCount() == 0) ? true : false; 
    }*/
    
    
    // Paging.
    public void changePagingState(ValueChangeEvent valueChange) 
    {
    	log.error("changePagingState: old=" + valueChange.getOldValue() + ", new=" + valueChange.getNewValue());
    	FacesContext.getCurrentInstance().renderResponse();
    }
        
    public int getFirstRow() 
    {
    	if (log.isDebugEnabled()) log.debug("getFirstRow " + firstScoreRow);
    	return firstScoreRow;
    }
    
    public void setFirstRow(int firstRow) 
    {
    	if (log.isDebugEnabled()) log.debug("setFirstRow from " + firstScoreRow + " to " + firstRow);
    	firstScoreRow = firstRow;
    }
    
    public int getRowCount()
    {
    	return retrieveListWebLabs().size();
    }


    
    
    
    
    
    
    
    
    
	public String processActionListProtocol() {

		protocol = new String();

		if (!isHasStepsCreated()) {
			protocol = "Passos ainda nao foram criados"; 
			return "listProtocol";
		}
		
		for (int i=0; i<wontovlabCurrentExperiment.getStepList().size(); i++ ) {

			protocol = protocol + ((i+1) + " - " + wontovlabCurrentExperiment.getStepList().get(i).getDescription() + "\n");

		}
		
		
		return "listProtocol";
	}
    
    public boolean isHasStepsCreated() {
    	try {
    		wontovlabCurrentExperiment = wpf.readAuthorshipXPDL(externalLogic.getSakaiHomePath() + "/authorshipExperiment_" + currentExperiment.getExperiment().getExperimentId().toString() + ".xpdl");
		} catch (Exception e) {
			System.out.println("============================================");
			System.out.println("Workflow de autoria ainda nao foi criado....");
			System.out.println(e.getMessage());
			System.out.println("============================================");
			hasStepsCreated = false;
			wontovlabCurrentExperiment = null;
			return hasStepsCreated;
		}
		
		System.out.println("=====================================");
		System.out.println("Workflow de autoria ja foi criado....");
		System.out.println("=====================================");
		hasStepsCreated = true;
    	return hasStepsCreated;
	}

	


    


    


    

    

    

}
