package riomhaire.lti.core.model.interfaces;

/**
 * A command dispatcher matches commands to actions that proccess them based off of some message
 *
 * @param <T> What object is returned by the command
 * @param <E> WHat execution environment is to be used (usually some form of Application Registry)
 * @param <P> The message the command can process

 */
public interface CommandDispatcher<R, E, P> {

    /**
     * This adds a mapping of a message type to the command that can handle that type
     * At the moment its a 1-1 mapping
     * @param commandName  name of command ... we allow this because we want a command to potentially respond to more than one message type
     * @param command   implementor
     * @return  Command dispatcher so we can have some form of fluwnt style construction.
     */
    CommandDispatcher<R, E, P> addCommand(String commandName, Command<R, E, P> command);

    /**
     * This is called by an invoker with
     *
     * @param environment  to execute within
     * @param message  the message to process.. the implementer of this interface should have a strategy of mapping message to command
     * @return response from executing the command
     */
    R dispatch(E environment, P message);
}
