/**************************************************************************
 *                                                                        *
 * The information in this document is proprietary to VeriSign, Inc.      *
 * It may not be used, reproduced or disclosed without the written        *
 * approval of VeriSign.                                                  *
 *                                                                        *
 * VERISIGN PROPRIETARY & CONFIDENTIAL INFORMATION                        *
 *                                                                        *
 *                                                                        *
 * Copyright (c) 2019 VeriSign, Inc.  All rights reserved.                *
 *                                                                        *
 *************************************************************************/

package com.verisign.epp.serverstub;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.verisign.epp.codec.changeext.EPPChangeExt;
import com.verisign.epp.codec.gen.EPPResponse;
import com.verisign.epp.codec.host.EPPHostCheckCmd;
import com.verisign.epp.codec.host.EPPHostCreateCmd;
import com.verisign.epp.codec.host.EPPHostDeleteCmd;
import com.verisign.epp.codec.host.EPPHostInfoCmd;
import com.verisign.epp.codec.host.EPPHostUpdateCmd;
import com.verisign.epp.codec.namestoreext.EPPNamestoreExtNamestoreExt;
import com.verisign.epp.codec.ttl.v1_0.EPPTtlCreate;
import com.verisign.epp.codec.ttl.v1_0.EPPTtlUpdate;
import com.verisign.epp.framework.EPPEvent;
import com.verisign.epp.framework.EPPEventResponse;
import com.verisign.epp.framework.EPPHostHandler;


/**
 * The {@code NSHostHandler} class is a concrete implementation of the abstract
 * {@link com.verisign.epp.framework.EPPHostHandler} class. It defines the
 * Server's response to all received EPP host Commands.
 */
public class NSHostHandler extends EPPHostHandler {

	/** 
	 * Logger category 
	 */
	    private static Logger cat = LoggerFactory.getLogger(NSHostHandler.class);
	      

	/**
	 * Namestore extension host handler, which is used when the namestore
	 * extension is passed.
	 */
	NamestoreExtHostHandler namestoreHostHandler = new NamestoreExtHostHandler();

	/** 
	 * EPP host handler as default handler for all host commands. 
	 */
	HostHandler hostHandler = new HostHandler();
	
	/**
	 * TTL Host Handler used for implementing the TTL extension draft (draft-ietf-regext-epp-ttl).
	 */
	TtlHostHandler ttlHostHandler = new TtlHostHandler();
	
	/**
	 * Change Domain Handler used for implementing the Change extension 
	 */
	RZHostHandler changeHostHandler = new RZHostHandler(); 
	


	/**
	 * Invoked when a Host Create Command is received. The handler routes the
	 * command to the appropriate handler based on the extensions and data
	 * included in the command.
	 *
	 * @param aEvent
	 *           The {@code EPPEvent} that is being handled
	 *
	 * @param aData
	 *           Any data that a Server needs to send to this
	 *           {@code EPPHostHandler}
	 *
	 * @return The response that should be sent back to the client.
	 *
	 * @see com.verisign.epp.framework.EPPHostHandler#doHostCreate(com.verisign.epp.framework.EPPEvent,
	 *      java.lang.Object)
	 */
	@Override
	protected EPPEventResponse doHostCreate(EPPEvent aEvent, Object aData) {
		EPPHostCreateCmd theCommand = (EPPHostCreateCmd) aEvent.getMessage();
		cat.debug("doHostCreate: command = [" + theCommand + "]");

		// TTL?
		if (theCommand.hasExtension(EPPTtlCreate.class)) {
			EPPEventResponse ttlResp = ttlHostHandler.doHostCreate(aEvent, aData);

			// Mirror NameStore Extension in response
			if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
				((EPPResponse) ttlResp.getResponse())
				      .addExtension(theCommand.getExtension(EPPNamestoreExtNamestoreExt.class));
			}
			
			return ttlResp;
		}
		
		// Change?
		if (theCommand.hasExtension(EPPChangeExt.class)) {
			EPPEventResponse changeResp = changeHostHandler.doHostCreate(aEvent, aData);

			// Mirror NameStore Extension in response
			if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
				((EPPResponse) changeResp.getResponse())
				      .addExtension(theCommand.getExtension(EPPNamestoreExtNamestoreExt.class));
			}
			
			return changeResp;
		}
		

		// NameStore Host Create Command?
		if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
			EPPEventResponse namestoreHostResponse = this.namestoreHostHandler.doHostCreate(aEvent, aData);

			return namestoreHostResponse;
		}

		EPPEventResponse hostCreateResponse = this.hostHandler.doHostCreate(aEvent, aData);
		return hostCreateResponse;
	}

	/**
	 * Invoked when a Host Delete Command is received. The handler routes the
	 * command to the appropriate handler based on the extensions and data
	 * included in the command.
	 *
	 * @param aEvent
	 *           The {@code EPPEvent} that is being handled
	 *
	 * @param aData
	 *           Any data that a Server needs to send to this
	 *           {@code EPPHostHandler}
	 *
	 * @return The response that should be sent back to the client.
	 *
	 * @see com.verisign.epp.framework.EPPHostHandler#doHostDelete(com.verisign.epp.framework.EPPEvent,
	 *      java.lang.Object)
	 */
	@Override
	protected EPPEventResponse doHostDelete(EPPEvent aEvent, Object aData) {
		EPPHostDeleteCmd theCommand = (EPPHostDeleteCmd) aEvent.getMessage();
		cat.debug("doHostDelete: command = [" + theCommand + "]");
		
		// Change?
		if (theCommand.hasExtension(EPPChangeExt.class)) {
			EPPEventResponse changeResp = changeHostHandler.doHostDelete(aEvent, aData);

			// Mirror NameStore Extension in response
			if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
				((EPPResponse) changeResp.getResponse())
				      .addExtension(theCommand.getExtension(EPPNamestoreExtNamestoreExt.class));
			}
			
			return changeResp;
		}
		

		// NameStore Host Delete Command?
		if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
			EPPEventResponse namestoreHostResponse = this.namestoreHostHandler.doHostDelete(aEvent, aData);

			return namestoreHostResponse;
		}

		EPPEventResponse hostDeleteResponse = this.hostHandler.doHostDelete(aEvent, aData);

		return hostDeleteResponse;
	}

	/**
	 * Invoked when a Host Info Command is received. The handler routes the
	 * command to the appropriate handler based on the extensions and data
	 * included in the command.
	 *
	 * @param aEvent
	 *           The {@code EPPEvent} that is being handled
	 *
	 * @param aData
	 *           Any data that a Server needs to send to this
	 *           {@code EPPHostHandler}
	 *
	 * @return The response that should be sent back to the client.
	 *
	 * @see com.verisign.epp.framework.EPPHostHandler#doHostInfo(com.verisign.epp.framework.EPPEvent,
	 *      java.lang.Object)
	 */
	@Override
	protected EPPEventResponse doHostInfo(EPPEvent aEvent, Object aData) {
		EPPHostInfoCmd theCommand = (EPPHostInfoCmd) aEvent.getMessage();
		cat.debug("doHostInfo: command = [" + theCommand + "]");
		
		// TTL?
		if (theCommand.getName().startsWith("ttl-")) {
			EPPEventResponse ttlResp = ttlHostHandler.doHostInfo(aEvent, aData);

			// Mirror NameStore Extension in response
			if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
				((EPPResponse) ttlResp.getResponse())
				      .addExtension(theCommand.getExtension(EPPNamestoreExtNamestoreExt.class));
			}

			return ttlResp;
		}

		// NameStore Host Info Command?
		if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
			EPPEventResponse namestoreHostResponse = this.namestoreHostHandler.doHostInfo(aEvent, aData);

			return namestoreHostResponse;
		}

		EPPEventResponse hostInfoResponse = this.hostHandler.doHostInfo(aEvent, aData);
		return hostInfoResponse;
	}

	/**
	 * Invoked when a Host Check Command is received. The handler routes the
	 * command to the appropriate handler based on the extensions and data
	 * included in the command.
	 *
	 * @param aEvent
	 *           The {@code EPPEvent} that is being handled
	 *
	 * @param aData
	 *           Any data that a Server needs to send to this
	 *           {@code EPPHostHandler}
	 *
	 * @return The response that should be sent back to the client.
	 *
	 * @see com.verisign.epp.framework.EPPHostHandler#doHostCheck(com.verisign.epp.framework.EPPEvent,
	 *      java.lang.Object)
	 */
	@Override
	protected EPPEventResponse doHostCheck(EPPEvent aEvent, Object aData) {
		EPPHostCheckCmd theCommand = (EPPHostCheckCmd) aEvent.getMessage();
		cat.debug("doHostCheck: command = [" + theCommand + "]");

		// NameStore Host Check Command?
		if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
			EPPEventResponse namestoreHostResponse = this.namestoreHostHandler.doHostCheck(aEvent, aData);

			return namestoreHostResponse;
		}

		EPPEventResponse hostCheckResponse = this.hostHandler.doHostCheck(aEvent, aData);

		return hostCheckResponse;
	}

	/**
	 * Invoked when a Host Update Command is received. The handler routes the
	 * command to the appropriate handler based on the extensions and data
	 * included in the command.
	 *
	 * @param aEvent
	 *           The {@code EPPEvent} that is being handled
	 *
	 * @param aData
	 *           Any data that a Server needs to send to this
	 *           {@code EPPHostHandler}
	 *
	 * @return The response that should be sent back to the client.
	 *
	 * @see com.verisign.epp.framework.EPPHostHandler#doHostUpdate(com.verisign.epp.framework.EPPEvent,
	 *      java.lang.Object)
	 */
	@Override
	protected EPPEventResponse doHostUpdate(EPPEvent aEvent, Object aData) {
		EPPHostUpdateCmd theCommand = (EPPHostUpdateCmd) aEvent.getMessage();
		cat.debug("doHostUpdate: command = [" + theCommand + "]");

		// TTL?
		if (theCommand.hasExtension(EPPTtlUpdate.class)) {
			EPPEventResponse ttlResp = ttlHostHandler.doHostUpdate(aEvent, aData);

			// Mirror NameStore Extension in response
			if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
				((EPPResponse) ttlResp.getResponse())
				      .addExtension(theCommand.getExtension(EPPNamestoreExtNamestoreExt.class));
			}
			
			return ttlResp;
		}
		
		// Change?
		if (theCommand.hasExtension(EPPChangeExt.class)) {
			EPPEventResponse changeResp = changeHostHandler.doHostUpdate(aEvent, aData);

			// Mirror NameStore Extension in response
			if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
				((EPPResponse) changeResp.getResponse())
				      .addExtension(theCommand.getExtension(EPPNamestoreExtNamestoreExt.class));
			}
			
			return changeResp;
		}
		
		
		// NameStore Host Update Command?
		if (theCommand.hasExtension(EPPNamestoreExtNamestoreExt.class)) {
			EPPEventResponse namestoreHostResponse = this.namestoreHostHandler.doHostUpdate(aEvent, aData);

			return namestoreHostResponse;
		}

		EPPEventResponse hostUpdateResponse = this.hostHandler.doHostUpdate(aEvent, aData);
		return hostUpdateResponse;
	}

}
