package kr.undo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import kr.miditunemodel.NoteEvent;

public abstract class Transaction {
	private List<Operation> ops = new ArrayList<Operation>();
		
	public Transaction()
	{
	}

	protected void add(Operation op)
	{
		ops.add(op);
	}
	
	public void undo()
	{
		for(int i = ops.size() - 1 ; i >= 0; i--)
		{
			ops.get(i).undo();
		}
	}
	
	private boolean isOpsValid()
	{
		//check all the ops to make sure they are valid
		for(Operation op : ops)
		{
			if(!op.isValid()) return false;
		}
		
		return true;
	}
	
	/**
	 * @return true if sucessful, false otherwise
	 */
	public boolean doIt()
	{
		//check all the ops to make sure they are valid
		if(!isOpsValid()) return false;

		//do the operation
		for(Operation op : ops)
		{
			op.doIt();
		}
		
		boolean valid;
		
		//check the resulting state to make sure its valid,
		//otherwise undo
		if(!(valid = isValid() && isOpsValid())) undo();
		
		return valid;
	}
	
	/**
	 * Called by doIt() after all ops are completed. Returns true if in a valid state,
	 * or false if the transaction should be undone.
	 */
	protected abstract boolean isValid();

	protected Collection<Operation> getOperations() {
		return ops;
	}
}
