
package org.sikuli.slides.sikuli;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.JLabel;
import javax.swing.SwingWorker;
import org.sikuli.slides.core.SikuliAction;
import org.sikuli.slides.listeners.tutorials.Observer;
import org.sikuli.slides.uis.TutorialConrollerUI;
import org.sikuli.slides.utils.Constants;
import org.sikuli.slides.utils.Constants.NavigationStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A Tutorial worker that processes users' interaction events when running the slides in tutorial mode.
 * This includes observing the controller UI to switch to the previous and next step in the tutorial mode. 
 * 
 * @author Khalid Alharbi
 *
 */

public class TutorialWorker extends SwingWorker<Boolean, Integer> implements Observer{
	private static final Logger logger = (Logger) LoggerFactory.getLogger(TutorialWorker.class);
	private static AtomicInteger currentStep=null;
	private List<SikuliAction> tasks=null;
	private final JLabel currentSlideLabel;
	private TutorialConrollerUI observable;
	
	public TutorialWorker(List<SikuliAction> tasks,JLabel currentSlideLabel,TutorialConrollerUI observable){
		this.tasks=tasks;
		this.currentSlideLabel=currentSlideLabel;
		currentStep=new AtomicInteger(-1);
		this.observable=observable;
		this.observable.register(this);
	}
	
	@Override
	protected Boolean doInBackground(){
		// Update the status. It sends data chunks to the process() method.
		publish(currentStep.get()+2);
		// run the first step
		doNextStep();
		
		return true;
	}

	@Override
	protected void done(){
	}
	@Override
	protected void process(List<Integer> stepsChunks){
		for(Integer step:stepsChunks){
			currentSlideLabel.setText((step).toString());
		}
	}
	
	private void doNextStep(){
		if(hasNextStep()){
			publish(currentStep.incrementAndGet()+1);
			tasks.get(currentStep.get()).doSikuliAction();
			doNextStep();
		}
	}
	
	/**
	 * Returns true if the presentation slides have more forward steps
	 * @return true if the presentation slides have more forward steps
	 */
	private boolean hasNextStep(){
		if(currentStep.get()<tasks.size()-1){
			return true;
		}
		else{
			logger.info("There are no next steps to move forward to.");
			return false;
		}
	}
	
	/**
	 * Returns true if the presentation slides have more backward steps
	 * @return true if the presentation slides have more backward steps
	 */
	private boolean hasPreviousStep(){
		if(currentStep.get()>0){
			return true;
		}
		else{
			logger.info("There are no previous steps to go back to.");
			return false;
		}
	}

	@Override
	public void update(NavigationStatus navigationStatus) {
		// Don't skip steps when wait action is being running
		//TODO: disable UI next, previous buttons instead of using this flag
		if(Constants.IsWaitAction){
			return;
		}
		
		if(navigationStatus.equals(NavigationStatus.NEXT)){
			if(hasNextStep()){
				Constants.IsNextStep=true;
			}
		}
		else if(navigationStatus.equals(NavigationStatus.PREVIOUS)){
			if(hasPreviousStep()){
				Constants.IsPreviousStep=true;
				currentStep.decrementAndGet();
				currentStep.decrementAndGet();
			}
		}
	}
}

@@ -29,16 +29,43 @@
 ikuli;%0A%0A
+import java.awt.Dimension;%0A
 import j
@@ -79,16 +79,16 @@
 l.List;%0A
-
 import j
@@ -184,24 +184,189 @@
 wingWorker;%0A
+import org.sikuli.api.DesktopScreenRegion;%0Aimport org.sikuli.api.ScreenRegion;%0Aimport org.sikuli.api.visual.Canvas;%0Aimport org.sikuli.api.visual.ScreenRegionCanvas;%0A
 import org.s
@@ -544,16 +544,111 @@
 stants;%0A
+import org.sikuli.slides.utils.MyScreen;%0Aimport org.sikuli.slides.utils.UserPreferencesEditor;%0A
 import o
@@ -1191,16 +1191,90 @@
 class);%0A
+%09private UserPreferencesEditor prefsEditor = new UserPreferencesEditor();%0A
 %09private
@@ -2588,32 +2588,63 @@
  forward to.%22);%0A
+%09%09%09showCompleteNotification();%0A
 %09%09%09return false;
@@ -2643,34 +2643,33 @@
 n false;%0A%09%09%7D%0A%09%7D%0A
-%09
 %0A
+
 %09/**%0A%09 * Returns
@@ -3536,17 +3536,632 @@
 );%0A%09%09%09%7D%0A
-
 %09%09%7D%0A%09%7D%0A
+%09%0A%09private void showCompleteNotification() %7B%0A%09%09Dimension screenDimension = MyScreen.getScreenDimensions();%0A%09%09int x = (int) (screenDimension.getWidth() / 2.0);%0A%09%09int y = (int) (screenDimension.getHeight() / 2.0);%0A%09%09ScreenRegion fullScreenRegion = new DesktopScreenRegion(Constants.ScreenId,%0A%09%09%09%09200,200,x, y);%0A%09%09Canvas canvas = new ScreenRegionCanvas(new DesktopScreenRegion(Constants.ScreenId));%0A%09%09canvas.addLabel(fullScreenRegion, %0A%09%09%09%09%22Great job! You have successfully completed this tutorial.%22)%0A%09%09%09%09.withFontSize(prefsEditor.getInstructionHintFontSize());%0A%09%09canvas.display(prefsEditor.getLabelDisplayTime());%0A%09%7D%0A
 %7D%0A

add label notification when the steps of the tutorial are completed