/***********************************************************
Copyright (C) 2019 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.codec.secureauthinfo;

import java.util.Vector;

import com.verisign.epp.codec.contact.EPPContactAddChange;
import com.verisign.epp.codec.contact.EPPContactAddress;
import com.verisign.epp.codec.contact.EPPContactCreateCmd;
import com.verisign.epp.codec.contact.EPPContactDisclose;
import com.verisign.epp.codec.contact.EPPContactPostalDefinition;
import com.verisign.epp.codec.contact.EPPContactUpdateCmd;
import com.verisign.epp.codec.domain.EPPDomainAddRemove;
import com.verisign.epp.codec.domain.EPPDomainCreateCmd;
import com.verisign.epp.codec.domain.EPPDomainInfoCmd;
import com.verisign.epp.codec.domain.EPPDomainStatus;
import com.verisign.epp.codec.domain.EPPDomainTransferCmd;
import com.verisign.epp.codec.domain.EPPDomainUpdateCmd;
import com.verisign.epp.codec.gen.EPPAuthInfo;
import com.verisign.epp.codec.gen.EPPCodecException;
import com.verisign.epp.codec.gen.EPPCodecTst;
import com.verisign.epp.codec.gen.EPPCommand;
import com.verisign.epp.codec.gen.EPPEncodeDecodeStats;
import com.verisign.epp.codec.gen.EPPFactory;
import com.verisign.epp.util.TestThread;
import com.verisign.epp.util.secureauthinfo.EPPAuthInfoFactory;

import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Is a unit test of supporting the Secure Authorization Information for
 * Transfer draft, which includes creating each of the sample commands and
 * responses in the draft.
 */
public class EPPSecureAuthInfoTst extends TestCase {
	/**
	 * Number of unit test iterations to run. This is set in
	 * {@code EPPCodecTst.main}
	 */
	static private long numIterations = 1;

	/**
	 * Creates a new EPPSecureAuthInfoTst object.
	 *
	 * @param name
	 *           Name of test
	 */
	public EPPSecureAuthInfoTst(String name) {
		super(name);
	}

	/**
	 * Unit test of the example of passing empty authorization information in an
	 * [RFC5731] domain name create command.
	 */
	public void testDomainCreate() {
		EPPDomainCreateCmd theCommand;
		EPPEncodeDecodeStats commandStats;

		EPPCodecTst.printStart("testDomainCreate");

		// Create a domain with just the domain name.
		theCommand = new EPPDomainCreateCmd("ABC-12345", "example.com", new EPPAuthInfo(""));

		commandStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(commandStats);

		EPPCodecTst.printEnd("testDomainCreate");
	}

	/**
	 * Unit test of the example of passing empty authorization information in an
	 * [RFC5733] contact create command.
	 */
	public void testContactCreate() {
		EPPContactCreateCmd theCommand;
		EPPEncodeDecodeStats commandStats;

		EPPCodecTst.printStart("testContactCreate");

		// Streets
		Vector streets = new Vector();
		streets.addElement("123 Example Dr.");
		streets.addElement("Suite 100");

		// Address
		EPPContactAddress address = new EPPContactAddress(streets, "Dulles", "VA", "20166-6503", "US");

		// Postal Definition
		EPPContactPostalDefinition name = new EPPContactPostalDefinition("John Doe", "Example Inc.",
		      EPPContactPostalDefinition.ATTR_TYPE_INT, address);

		// Contact Command
		theCommand = new EPPContactCreateCmd("ABC-12345", "DepDisclose", name, "jdoe@example.com", new EPPAuthInfo(""));
		theCommand.setFax("+1.7035555556");
		theCommand.setVoice("+1.7035555555");
		theCommand.setVoiceExt("1234");

		EPPContactDisclose disclose = new EPPContactDisclose();
		disclose.setFlag(false);
		disclose.setVoice(true);
		disclose.setEmail(true);

		theCommand.setDisclose(disclose);

		commandStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(commandStats);

		EPPCodecTst.printEnd("testContactCreate");
	}

	/**
	 * Unit test of the example of removing the "clientTransferProhibited" status
	 * and setting the authorization information in an [RFC5731] domain name
	 * update command.
	 */
	public void testDomainUpdateSet() {
		EPPCodecTst.printStart("testDomainUpdateSet");

		// remove
		Vector removeStatuses = new Vector();
		removeStatuses.addElement(new EPPDomainStatus(EPPDomainStatus.ELM_STATUS_CLIENT_TRANSFER_PROHIBITED));
		EPPDomainAddRemove removeItems = new EPPDomainAddRemove();
		removeItems.setStatuses(removeStatuses);

		// change
		EPPDomainAddRemove changeItems = new EPPDomainAddRemove();
		changeItems.setAuthInfo(EPPAuthInfoFactory.createAuthInfo(20));

		EPPDomainUpdateCmd theCommand = new EPPDomainUpdateCmd("ABC-12345-XYZ", "example.com", null, removeItems,
		      changeItems);

		EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(commandStats);
	}

	/**
	 * Unit test of the example of unsetting the authorization information
	 * explicitly in an [RFC5731] domain name update command.
	 */
	public void testDomainUpdateUnsetNull() {
		EPPCodecTst.printStart("testDomainUpdateUnsetNull");

		// add
		Vector addStatuses = new Vector();
		addStatuses.addElement(new EPPDomainStatus(EPPDomainStatus.ELM_STATUS_CLIENT_TRANSFER_PROHIBITED));
		EPPDomainAddRemove addItems = new EPPDomainAddRemove();
		addItems.setStatuses(addStatuses);

		// change
		EPPDomainAddRemove changeItems = new EPPDomainAddRemove();
		EPPAuthInfo nullAuthInfo = new EPPAuthInfo();
		nullAuthInfo.removePassword();
		changeItems.setAuthInfo(nullAuthInfo);

		EPPDomainUpdateCmd theCommand = new EPPDomainUpdateCmd("ABC-12345-XYZ", "example.com", addItems, null,
		      changeItems);

		EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(commandStats);

		EPPCodecTst.printEnd("testDomainUpdateUnsetNull");
	}

	/**
	 * Unit test of the example of unsetting the authorization information with
	 * an empty authorization information in an [RFC5731] domain name update
	 * command.
	 */
	public void testDomainUpdateUnsetEmpty() {
		EPPCodecTst.printStart("testDomainUpdateUnsetEmpty");

		// add
		Vector addStatuses = new Vector();
		addStatuses.addElement(new EPPDomainStatus(EPPDomainStatus.ELM_STATUS_CLIENT_TRANSFER_PROHIBITED));
		EPPDomainAddRemove addItems = new EPPDomainAddRemove();
		addItems.setStatuses(addStatuses);

		// change
		EPPDomainAddRemove changeItems = new EPPDomainAddRemove();
		changeItems.setAuthInfo(new EPPAuthInfo(""));

		EPPDomainUpdateCmd theCommand = new EPPDomainUpdateCmd("ABC-12345-XYZ", "example.com", addItems, null,
		      changeItems);

		EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(commandStats);

		EPPCodecTst.printEnd("testDomainUpdateUnsetEmpty");
	}

	/**
	 * Unit test of the example of unsetting the authorization information with
	 * an empty authorization information in an [RFC5733] contact update command
	 */
	public void testContactUpdateUnsetEmpty() {
		EPPContactUpdateCmd theCommand = null;
		EPPEncodeDecodeStats commandStats = null;

		EPPCodecTst.printStart("testContactUpdateUnsetEmpty");

		// change
		EPPContactAddChange changeItems = new EPPContactAddChange();
		changeItems.setAuthInfo(new EPPAuthInfo(""));

		// Update Command
		theCommand = new EPPContactUpdateCmd("ABC-12345-XYZ", "sh8013", null, null, changeItems);

		commandStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(commandStats);

		EPPCodecTst.printEnd("testContactUpdateUnsetEmpty");
	}

	/**
	 * Unit test of the example of passing a non-empty authorization information
	 * in an [RFC5731] domain name info command to verify the authorization
	 * information value.
	 */
	public void testDomainInfo() {
		EPPCodecTst.printStart("testDomainInfo");

		EPPDomainInfoCmd theCommand;
		theCommand = new EPPDomainInfoCmd("ABC-12345", "example.com");
		theCommand.setAuthInfo(EPPAuthInfoFactory.createAuthInfo(20));

		EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(commandStats);

		EPPCodecTst.printEnd("testDomainInfo");
	}

	/**
	 * Unit test of the example of passing a non-empty authorization information
	 * in an [RFC5731] domain name transfer request command to authorize the
	 * transfer.
	 */
	public void testDomainTransfer() {
		EPPDomainTransferCmd theCommand;
		EPPEncodeDecodeStats commandStats;

		EPPCodecTst.printStart("testDomainTransfer");

		// Test Transfer Request Command (without authInfo roid)
		theCommand = new EPPDomainTransferCmd("ABC-12345", EPPCommand.OP_REQUEST, "example.com",
		      EPPAuthInfoFactory.createAuthInfo(20), null);

		commandStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(commandStats);

		EPPCodecTst.printEnd("testDomainTransfer");
	}

	/**
	 * JUNIT {@code setUp} method, which sets the default client Id to
	 * "theRegistrar" and initializes the {@code EPPDomainMapFactory} with the
	 * {@code EPPCodec}.
	 */
	@Override
	protected void setUp() {
	}

	/**
	 * JUNIT {@code tearDown}, which currently does nothing.
	 */
	@Override
	protected void tearDown() {
	}

	/**
	 * JUNIT {@code suite} static method, which returns the tests associated with
	 * {@code EPPSecureAuthInfoTst}.
	 *
	 * @return Tests to execute
	 */
	public static Test suite() {
		EPPCodecTst.initEnvironment();

		TestSuite suite = new TestSuite(EPPSecureAuthInfoTst.class);

		// iterations Property
		String numIterProp = System.getProperty("iterations");

		if (numIterProp != null) {
			numIterations = Integer.parseInt(numIterProp);
		}

		// Add map factories the EPPCodec.
		try {
			EPPFactory.getInstance().addMapFactory("com.verisign.epp.codec.host.EPPHostMapFactory");
			EPPFactory.getInstance().addMapFactory("com.verisign.epp.codec.domain.EPPDomainMapFactory");
			EPPFactory.getInstance().addMapFactory("com.verisign.epp.codec.contact.EPPContactMapFactory");
		}
		catch (EPPCodecException e) {
			Assert.fail("EPPCodecException adding EPPDomainMapFactory to EPPCodec: " + e);
		}

		return suite;
	}

	/**
	 * Unit test main, which accepts the following system property options: <br>
	 *
	 * <ul>
	 * <li>iterations Number of unit test iterations to run</li>
	 * <li>validate Turn XML validation on ({@code true}) or off (
	 * {@code false}). If validate is not specified, validation will be off.</li>
	 * </ul>
	 *
	 *
	 * @param args
	 *           Command line arguments
	 */
	public static void main(String[] args) {
		// Number of Threads
		int numThreads = 1;
		String threadsStr = System.getProperty("threads");

		if (threadsStr != null) {
			numThreads = Integer.parseInt(threadsStr);
		}

		// Run test suite in multiple threads?
		if (numThreads > 1) {
			// Spawn each thread passing in the Test Suite
			for (int i = 0; i < numThreads; i++) {
				TestThread thread = new TestThread("EPPSecureAuthInfoTst Thread " + i, EPPSecureAuthInfoTst.suite());
				thread.start();
			}
		}
		else { // Single threaded mode.
			junit.textui.TestRunner.run(EPPSecureAuthInfoTst.suite());
		}
	}

	/**
	 * Sets the number of iterations to run per test.
	 *
	 * @param aNumIterations
	 *           number of iterations to run per test
	 */
	public static void setNumIterations(long aNumIterations) {
		numIterations = aNumIterations;
	}

}
