package org.apollo.util.plugin;

import org.apollo.ServerContext;
import org.apollo.game.GameService;
import org.apollo.game.command.CommandListener;
import org.apollo.game.event.Event;
import org.apollo.game.event.handler.EventHandler;
import org.apollo.game.event.handler.chain.EventHandlerChain;
import org.apollo.game.event.handler.chain.EventHandlerChainGroup;
import org.apollo.game.login.LoginListener;
import org.apollo.game.login.LogoutListener;
import org.apollo.game.model.World;
import org.apollo.net.release.EventDecoder;
import org.apollo.net.release.EventEncoder;
import org.apollo.net.release.Release;

/**
 * The {@link PluginContext} contains methods a plugin can use to interface with the server, for example, by adding
 * {@link EventHandler}s to {@link EventHandlerChain}s.
 * 
 * @author Graham
 */
public final class PluginContext {

	/**
	 * The server context.
	 */
	private final ServerContext context;

	/**
	 * Creates the plugin context.
	 * 
	 * @param context The server context.
	 */
	public PluginContext(ServerContext context) {
		this.context = context;
	}

	/**
	 * Adds a {@link CommandListener}.
	 * 
	 * @param name The name of the listener.
	 * @param listener The listener.
	 */
	public void addCommandListener(String name, CommandListener listener) {
		World.getWorld().getCommandDispatcher().register(name, listener);
	}

	/**
	 * Adds an {@link EventDecoder}.
	 * 
	 * @param <T> The type of decoder.
	 * @param releaseNo The release number.
	 * @param opcode The opcode.
	 * @param decoder The event decoder.
	 */
	public <T extends Event> void addEventDecoder(int releaseNo, int opcode, EventDecoder<T> decoder) {
		Release release = context.getRelease();
		if (release.getReleaseNumber() == releaseNo) {
			release.register(opcode, decoder);
		}
	}

	/**
	 * Adds an {@link EventEncoder}.
	 * 
	 * @param <E> The type of encoder.
	 * @param releaseNo The release number.
	 * @param event The event.
	 * @param encoder The event encoder.
	 */
	public <E extends Event> void addEventEncoder(int releaseNo, Class<E> event, EventEncoder<E> encoder) {
		Release release = context.getRelease();
		if (release.getReleaseNumber() == releaseNo) {
			release.register(event, encoder);
		}
	}

	/**
	 * Adds an {@link EventHandler} to the end of the chain.
	 * 
	 * @param <E> The type of event.
	 * @param event The event.
	 * @param handler The handler.
	 */
	public <E extends Event> void addLastEventHandler(Class<E> event, EventHandler<E> handler) {
		EventHandlerChainGroup chains = context.getService(GameService.class).getEventHandlerChains();
		EventHandlerChain<E> chain = chains.getChain(event);
		if (chain == null) {
			chain = new EventHandlerChain<>(handler);
			chains.register(event, chain);
		} else {
			chain.addLast(handler);
		}
	}

	/**
	 * Adds a {@link LoginListener}.
	 * 
	 * @param listener The listener.
	 */
	public void addLoginListener(LoginListener listener) {
		World.getWorld().getLoginDispatcher().register(listener);
	}

	/**
	 * Adds a {@link LogoutListener}.
	 * 
	 * @param listener The listener.
	 */
	public void addLogoutListener(LogoutListener listener) {
		World.getWorld().getLogoutDispatcher().register(listener);
	}

}
@@ -487,135 +487,8 @@
 rld;
-%0Aimport org.apollo.net.release.EventDecoder;%0Aimport org.apollo.net.release.EventEncoder;%0Aimport org.apollo.net.release.Release;
 %0A%0A/*
@@ -1235,873 +1235,8 @@
 %09%7D%0A%0A
-%09/**%0A%09 * Adds an %7B@link EventDecoder%7D.%0A%09 * %0A%09 * @param %3CT%3E The type of decoder.%0A%09 * @param releaseNo The release number.%0A%09 * @param opcode The opcode.%0A%09 * @param decoder The event decoder.%0A%09 */%0A%09public %3CT extends Event%3E void addEventDecoder(int releaseNo, int opcode, EventDecoder%3CT%3E decoder) %7B%0A%09%09Release release = context.getRelease();%0A%09%09if (release.getReleaseNumber() == releaseNo) %7B%0A%09%09%09release.register(opcode, decoder);%0A%09%09%7D%0A%09%7D%0A%0A%09/**%0A%09 * Adds an %7B@link EventEncoder%7D.%0A%09 * %0A%09 * @param %3CE%3E The type of encoder.%0A%09 * @param releaseNo The release number.%0A%09 * @param event The event.%0A%09 * @param encoder The event encoder.%0A%09 */%0A%09public %3CE extends Event%3E void addEventEncoder(int releaseNo, Class%3CE%3E event, EventEncoder%3CE%3E encoder) %7B%0A%09%09Release release = context.getRelease();%0A%09%09if (release.getReleaseNumber() == releaseNo) %7B%0A%09%09%09release.register(event, encoder);%0A%09%09%7D%0A%09%7D%0A%0A
 %09/**

Remove unused methods from PluginContext.