/***********************************************************
 Copyright (C) 2004 VeriSign, Inc.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

 http://www.verisign.com/nds/naming/namestore/techdocs.html
 ***********************************************************/
package com.verisign.epp.rootzone.util;

import java.util.Date;
import java.util.HashMap;

import com.verisign.epp.codec.change.type.EPPChangeAction;
import com.verisign.epp.codec.change.type.EPPChangeCheckData;
import com.verisign.epp.codec.change.type.EPPChangeRequest;
import com.verisign.epp.codec.change.type.EPPChangeUpdateAttributes;

/**
 * Emulates the Root Zone Management System. Stores a mapping between RequestId
 * and Change Request object. Sequential Create, Update, and Info commands
 * should yield realistic results.
 */
public abstract class RootZoneManager {
	/**
	 * This is a map from RequestId to ChangeRequest
	 */
	static private HashMap map = new HashMap();

	/**
	 * Adds the ChangeRequest object to the RootZoneManager
	 * 
	 * @param request
	 *           ChangeRequest object to add
	 * @return <code>true</code> if and only if the record was inserted
	 *         correctly. <code>false</code> if the record already exists
	 */
	static public boolean addChangeRequest(EPPChangeRequest request) {
		if (request == null)
			return false;
		String requestId = request.getRequestId();
		if (isChangeRequest(requestId))
			return false;
		if (request.getPriority() == null)
			request.setPriority(RootZonePriority.NORMAL);
		request.setStatus(RootZoneStatus.INITIAL);
		request.setCreatedDate(new Date());
		request.setUpdatedDate(new Date());
		request.setCreatedId("CreatedIdSetByTheServer");
		request.setUpdatedId("UpdatedIdSetByTheServer");
		putChangeRequest(requestId, request);
		return true;
	}

	/**
	 * Adds the ChangeAction object to the specified ChangeRequest
	 * 
	 * @param request
	 *           EPPChangeRequest on which to append
	 * @param action
	 *           ChangeAction object to add
	 * @return <code>true</code> if and only if the record was inserted
	 *         <code>false</code> if the ChangeRequest does not exist
	 */
	static public boolean addChangeAction(EPPChangeRequest request, EPPChangeAction action) {
		return addChangeAction(request.getRequestId(), action);
	}

	/**
	 * Adds the ChangeAction object to the specified ChangeRequest
	 * 
	 * @param requestId
	 *           ChangeRequestId on which to append
	 * @param action
	 *           ChangeAction object to add
	 * @return <code>true</code> if and only if the record was inserted
	 *         <code>false</code> if the ChangeRequest does not exist
	 */
	static public boolean addChangeAction(String requestId, EPPChangeAction action) {
		if (action == null)
			return false;
		if (!isChangeRequest(requestId))
			return false;
		EPPChangeRequest request = getChangeRequest(requestId);
		request.addAction(action);
		return true;
	}

	/**
	 * Retrieve the ChangeRequest object to the specified Change RequestId
	 * 
	 * @param requestId
	 *           Change RequestId to retrieve
	 * @return <code>EPPChangeRequest</code> object
	 */
	static public EPPChangeRequest findChangeRequest(String requestId) {
		EPPChangeRequest request = null;
		if (isChangeRequest(requestId))
			request = (EPPChangeRequest) map.get(requestId);
		return request;
	}

	/**
	 * Update the ChangeRequest object with the specified Change RequestId
	 * 
	 * @param requestId
	 *           Change RequestId to update
	 * @param attrs
	 *           Change request attributes
	 * @return <code>true</code> if and only if the record was updated
	 *         <code>false</code> if the ChangeRequest does not exist
	 */
	static public boolean updateChangeRequest(String requestId, EPPChangeUpdateAttributes attrs) {
		if (!isChangeRequest(requestId))
			return false;
		EPPChangeRequest request = findChangeRequest(requestId);
		request.updateAttributes(attrs);
		return true;
	}

	/**
	 * Clear the ChangeRequest object with the specified Change RequestId
	 * 
	 * @param requestId
	 *           Change RequestId to clear
	 * @return <code>true</code> if and only if the record was updated
	 *         <code>false</code> if the ChangeRequest does not exist
	 */
	static public boolean clearChangeRequest(String requestId) {
		if (!isChangeRequest(requestId))
			return false;
		EPPChangeRequest request = findChangeRequest(requestId);
		request.clearActions();
		return true;
	}

	/**
	 * Submit the ChangeRequest object with the specified Change RequestId
	 * 
	 * @param requestId
	 *           Change RequestId to submit
	 * @return <code>true</code> if and only if the record was updated
	 *         <code>false</code> if the ChangeRequest does not exist
	 */
	static public boolean submitChangeRequest(String requestId) {
		if (!isChangeRequest(requestId))
			return false;
		EPPChangeRequest request = findChangeRequest(requestId);
		request.setStatus(RootZoneStatus.SUBMITTED);
		return true;
	}

	/**
	 * Withdraw the ChangeRequest object with the specified Change RequestId
	 * 
	 * @param requestId
	 *           Change RequestId to withdraw
	 * @return <code>true</code> if and only if the record was updated
	 *         <code>false</code> if the ChangeRequest does not exist
	 */
	static public boolean withdrawChangeRequest(String requestId) {
		if (!isChangeRequest(requestId))
			return false;
		EPPChangeRequest request = findChangeRequest(requestId);
		request.setStatus(RootZoneStatus.IANA_WITHDRAWN);
		return true;
	}

	/**
	 * Delete the ChangeRequest object with the specified Change RequestId
	 * 
	 * @param requestId
	 *           Change RequestId to delete
	 * @return <code>true</code> if and only if the record was delete
	 *         <code>false</code> if the ChangeRequest does not exist
	 */
	static public boolean deleteChangeRequest(String requestId) {
		if (!isChangeRequest(requestId))
			return false;
		removeChangeRequest(requestId);
		return true;
	}

	/**
	 * Check the ChangeRequest object with the specified Change RequestId
	 * 
	 * @param requestId
	 *           Change RequestId to check
	 * @return <code>true</code> if and only if the record exists
	 *         <code>false</code> if the ChangeRequest does not exist
	 */
	static public EPPChangeCheckData checkChangeRequest(String requestId) {
		return new EPPChangeCheckData(requestId, isChangeRequest(requestId));
	}

	static private boolean isChangeRequest(String requestId) {
		return map.containsKey(requestId);
	}

	static private EPPChangeRequest getChangeRequest(String requestId) {
		return (EPPChangeRequest) map.get(requestId);
	}

	static private EPPChangeRequest putChangeRequest(String requestId, EPPChangeRequest request) {
		return (EPPChangeRequest) map.put(requestId, request);
	}

	static private EPPChangeRequest removeChangeRequest(String requestId) {
		return (EPPChangeRequest) map.remove(requestId);
	}

}
