package ru.rsdn.patterns.mvc.controller;

import java.util.Stack;

import ru.rsdn.patterns.behavioral.command.ICommand;
import ru.rsdn.patterns.mvc.model.Model;

/**
 * Контроллер
 * @param <M> модель
 * @param
 * <P>
 * свойство модели
 */
public class Controller<M extends Model<P>, P> {
	private M model;

	private final Stack<ICommand<M>> undoCommands = new Stack<ICommand<M>>();

	private final Stack<ICommand<M>> redoCommands = new Stack<ICommand<M>>();

	/**
	 * Установить модель
	 * @param _model модель
	 */
	public void setModel(M _model) {
		model = _model;
		undoCommands.clear();
		redoCommands.clear();
	}

	/**
	 * Запрос на выполнение команды
	 * @param command команда
	 */
	public void query(ICommand<M> command) {
		if (command == null)
			throw new NullPointerException("Пустой параметр");
		execute(command, undoCommands);
	}

	private void execute(ICommand<M> command, Stack<ICommand<M>> stack) {
		if (model != null) {
			final ICommand<M> undoCommand = command.execute(model);
			if (undoCommand != null)
				stack.push(undoCommand);
		}
	}

	/**
	 * Запрос на отмену последнего выполненного запроса
	 */
	public void queryUndo() {
		if (!undoCommands.isEmpty()) {
			final ICommand<M> command = undoCommands.pop();
			execute(command, redoCommands);
		}
	}

	/**
	 * Запрос на повторное выполнение последнего отмененного запроса
	 */
	public void queryRedo() {
		if (!redoCommands.isEmpty()) {
			final ICommand<M> command = redoCommands.pop();
			execute(command, undoCommands);
		}
	}
}
