package ch.openech.mj.edit;

import java.util.List;

import ch.openech.mj.application.DevMode;
import ch.openech.mj.edit.form.IForm;
import ch.openech.mj.edit.form.SwitchForm;
import ch.openech.mj.edit.validation.Indicator;
import ch.openech.mj.edit.validation.ValidationMessage;
import ch.openech.mj.toolkit.IAction;
import ch.openech.mj.toolkit.IComponent;
import ch.openech.mj.toolkit.ResourceActionEnabled;

public abstract class Wizard<T> extends Editor<T> {

	private WizardStep<?> currentStep;
	private int currentStepIndex = 0;
	
	protected final PreviousWizardStepAction prevAction;
	protected final NextWizardStepAction nextAction;
	private SwitchForm<T> switchForm;
	private final Indicator indicator;
	private final EditorListener stepFinishedListener;
	
	protected Wizard() {
		nextAction = new NextWizardStepAction();
		prevAction = new PreviousWizardStepAction();
		indicator = new WizardIndicator();
		stepFinishedListener = new WizardStepFinishedListener();
	}

	protected abstract WizardStep<?> getFirstStep();
	
	@Override
	public IAction[] getActions() {
		if (DevMode.isActive()) {
			return new IAction[]{demoAction, cancelAction, prevAction, nextAction, saveAction};
		} else {
			return new IAction[]{cancelAction, prevAction, nextAction, saveAction};
		}
	}

	@Override
	public void save() {
		currentStep.save();
		super.save();
	}

	protected int getCurrentStepIndex() {
		return currentStepIndex;
	}
	
	private class NextWizardStepAction extends ResourceActionEnabled {
		@Override
		public void action(IComponent context) {
			currentStep.save();
		}
	}

	private class PreviousWizardStepAction extends ResourceActionEnabled {
		@Override
		public void action(IComponent context) {
			currentStep.cancel();
		}
	}

	@Override
	protected final IForm<T> createForm() {
		switchForm = new SwitchForm<T>();
		return switchForm;
	}
	
	@Override
	public IForm<T> startEditor() {
		IForm<T> formVisual = super.startEditor();
		setCurrentStep(getFirstStep());
		return formVisual;
	}

	private void setCurrentStep(WizardStep<?> step) {
		currentStep = step;
		currentStep.setIndicator(indicator);
		currentStep.setEditorListener(stepFinishedListener);
 
		IForm<?> form = currentStep.startEditor();
		switchForm.setForm(form);
		// ClientToolkit.getToolkit().focusFirstComponent(form.getComponent());
		
		prevAction.setEnabled(currentStepIndex > 0);
	}
	
	protected void commit() {
		if (currentStep.isSaveable()) {
			currentStep.save();
		}
	}
	
	@Override
	protected void finish() {
		currentStep.finish();
		super.finish();
	}

	@Override
	protected abstract Object save(T object) throws Exception;
	
	private class WizardIndicator implements Indicator {

		@Override
		public void setValidationMessages(List<ValidationMessage> validationResult) {
			nextAction.setEnabled(validationResult.isEmpty() && currentStep.getNextStep() != null);
			saveAction.setEnabled(validationResult.isEmpty() && currentStep.canFinish());
		}
	}
	
	private class WizardStepFinishedListener implements EditorListener {

		@Override
		public void saved(Object saveResult) {
			WizardStep<?> nextStep = currentStep.getNextStep();
			if (nextStep != null) {
				currentStepIndex++;
				setCurrentStep(nextStep);
			} else {
				save();
			}
		}

		@Override
		public void canceled() {
			currentStepIndex--;
			setCurrentStep(currentStep.getPreviousStep());
		}
	}
	
	@Override
	public void fillWithDemoData() {
		currentStep.fillWithDemoData();
	}
	 
}

@@ -1360,36 +1360,147 @@
 %0D%0A%09%09
-currentStep.save();%0D%0A%09%09super
+// WizardFinishedListener will trigger save of wizard object%0D%0A%09%09currentStep.setEditorListener(new WizardFinishedListener());%0D%0A%09%09currentStep
 .sav
@@ -3362,37 +3362,8 @@
 );%0D%0A
-%09%09%09if (nextStep != null) %7B%0D%0A%09
 %09%09%09c
@@ -3382,17 +3382,16 @@
 dex++;%0D%0A
-%09
 %09%09%09setCu
@@ -3416,40 +3416,8 @@
 );%0D%0A
-%09%09%09%7D else %7B%0D%0A%09%09%09%09save();%0D%0A%09%09%09%7D%0D%0A
 %09%09%7D%0D
@@ -3539,32 +3539,257 @@
 );%0D%0A%09%09%7D%0D%0A%09%7D%0D%0A%09%0D%0A
+%09private class WizardFinishedListener implements EditorListener %7B%0D%0A%0D%0A%09%09@Override%0D%0A%09%09public void saved(Object saveResult) %7B%0D%0A%09%09%09Wizard.super.save();%0D%0A%09%09%7D%0D%0A%0D%0A%09%09@Override%0D%0A%09%09public void canceled() %7B%0D%0A%09%09%09// not used%0D%0A%09%09%7D%0D%0A%09%7D%0D%0A%09%0D%0A
 %09@Override%0D%0A%09pub

Fix on save