/***********************************************************
Copyright (C) 2018 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.launchpolicy.v01;

import java.util.Date;
import java.util.GregorianCalendar;

import com.verisign.epp.codec.gen.EPPCodecException;
import com.verisign.epp.codec.gen.EPPCodecTst;
import com.verisign.epp.codec.gen.EPPEncodeDecodeStats;
import com.verisign.epp.codec.gen.EPPFactory;
import com.verisign.epp.codec.gen.EPPTransId;
import com.verisign.epp.codec.registry.v02.EPPRegistryCreateCmd;
import com.verisign.epp.codec.registry.v02.EPPRegistryInfoResp;
import com.verisign.epp.codec.registry.v02.EPPRegistryMapFactory;
import com.verisign.epp.codec.registry.v02.EPPRegistryServices;
import com.verisign.epp.codec.registry.v02.EPPRegistryServices.EPPRegistryObjURI;
import com.verisign.epp.codec.registry.v02.EPPRegistryServicesExt;
import com.verisign.epp.codec.registry.v02.EPPRegistryServicesExt.EPPRegistryExtURI;
import com.verisign.epp.codec.registry.v02.EPPRegistryTst;
import com.verisign.epp.codec.registry.v02.EPPRegistryUpdateCmd;
import com.verisign.epp.codec.registry.v02.EPPRegistryZone;
import com.verisign.epp.codec.registry.v02.EPPRegistryZoneData;
import com.verisign.epp.util.TestThread;

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

/**
 * Test of the packet encoder and decoder (CODEC) for the Launch Phase Policy
 * Extension. The Launch Phase Policy Extension is a command / response
 * extension of a zone object in the Registry Mapping. The
 * {@link EPPRegistryTst} utility methods are used to supporting creating a full
 * Registry Mapping command or response that is extended by the Launch Phase
 * Policy Extension.
 */
public class EPPLaunchPolicyTst extends TestCase {
	/**
	 * Number of unit test iterations to run. This is set in
	 * <code>EPPCodecTst.main</code>
	 */
	static private long numIterations = 1;

	public EPPLaunchPolicyTst(String name) {
		super(name);
	}

	/**
	 * Test the registry info response for the zone info that includes the Launch
	 * Policy Extension.
	 */
	public void testRegistryInfoZoneInfo() {
		EPPCodecTst.printStart("testRegistryInfoZoneInfo");

		// Create a Registry Info Response
		EPPTransId theTransId = new EPPTransId("ABC-12345", "54321-XYZ");
		EPPRegistryZone zoneInfo = EPPRegistryTst.createZone();
		EPPRegistryInfoResp theResponse = new EPPRegistryInfoResp(theTransId, new EPPRegistryZoneData(zoneInfo, true));

		// Add the Launch Phase Policy Extension
		EPPLaunchPolicyInfData launchPolicyExt = new EPPLaunchPolicyInfData(buildLaunchPolicyZone());
		theResponse.addExtension(launchPolicyExt);

		EPPEncodeDecodeStats responseStats = EPPCodecTst.testEncodeDecode(theResponse);
		System.out.println(responseStats);

		EPPCodecTst.printEnd("testRegistryInfoZoneInfo");
	}

	/**
	 * Test the registry create command with the zone info that includes the
	 * Launch Policy Extension.
	 */
	public void testRegistryCreate() {
		EPPCodecTst.printStart("testRegistryCreate");

		EPPRegistryZone zone = EPPRegistryTst.createZone();
		zone.setName("newtld");

		EPPRegistryCreateCmd theCommand = null;
		theCommand = new EPPRegistryCreateCmd("ABC-12349", zone);

		// Add the Launch Phase Policy Extension
		EPPLaunchPolicyCreate launchPolicyExt = new EPPLaunchPolicyCreate(buildLaunchPolicyZone());
		theCommand.addExtension(launchPolicyExt);

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

		EPPCodecTst.printEnd("testRegistryCreate");
	}

	/**
	 * Test the registry update command with the zone info that includes the
	 * Launch Policy Extension.
	 */
	public void testRegistryUpdate() {
		EPPCodecTst.printStart("testRegistryUpdate");

		EPPRegistryZone zone = new EPPRegistryZone();
		zone.setName("newtld");

		EPPRegistryUpdateCmd theCommand = null;
		theCommand = new EPPRegistryUpdateCmd("ABC-12349", zone);

		zone.setDomain(EPPRegistryTst.buildInfoDomain());
		zone.setHost(EPPRegistryTst.buildInfoHost(true));
		zone.setContact(EPPRegistryTst.buildContact());

		EPPRegistryServices services = new EPPRegistryServices();
		services.addObjURI(new EPPRegistryObjURI(EPPRegistryMapFactory.NS, Boolean.TRUE));
		EPPRegistryServicesExt svcExt = new EPPRegistryServicesExt();
		services.setExtension(svcExt);
		svcExt.addExtURI(new EPPRegistryExtURI(EPPRegistryMapFactory.NS, Boolean.TRUE));
		zone.setServices(services);

		zone.setCreatedBy("crId");
		zone.setCreatedDate(new Date());

		// Add the Launch Phase Policy Extension
		EPPLaunchPolicyUpdate launchPolicyExt = new EPPLaunchPolicyUpdate(buildLaunchPolicyZone());
		theCommand.addExtension(launchPolicyExt);

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

		EPPCodecTst.printEnd("testRegistryUpdate");
	}

	/**
	 * 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</code>) or off (
	 * <code>false</code>). If validate is not specified, validation will be off.
	 * </li>
	 * </ul>
	 * 
	 * 
	 * @param args
	 *           Program 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("EPPRegistryTst Thread " + i, EPPLaunchPolicyTst.suite());
				thread.start();
			}
		}
		else { // Single threaded mode.
			junit.textui.TestRunner.run(EPPLaunchPolicyTst.suite());
		}
	}

	/**
	 * JUNIT <code>suite</code> static method, which returns the tests associated
	 * with <code>EPPRegistryTst</code>.
	 * 
	 * @return Test suite
	 */
	public static Test suite() {
		EPPCodecTst.initEnvironment();

		TestSuite suite = new TestSuite(EPPLaunchPolicyTst.class);

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

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

		// Add the factories to the EPPCodec.
		try {
			EPPFactory.getInstance().addMapFactory("com.verisign.epp.codec.registry.v02.EPPRegistryMapFactory");
			EPPFactory.getInstance().addExtFactory("com.verisign.epp.codec.launchpolicy.v01.EPPLaunchPolicyExtFactory");
		}
		catch (EPPCodecException e) {
			Assert.fail("EPPCodecException adding factories to EPPCodec: " + e);
		}

		return suite;
	}

	/**
	 * JUNIT <code>setUp</code>, which currently does nothing.
	 */
	protected void setUp() {
	}

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

	/**
	 * 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;
	}

	/**
	 * Build a populated {@link EPPLaunchPolicyZone} instance that can be
	 * included in one of the Launch Policy Extensions. The populated attributes
	 * are based on the sample included in draft-gould-regext-launch-policy. The
	 * following phases are added to the populated {@link EPPLaunchPolicyZone}
	 * instance:<br>
	 * <ol>
	 * <li>Sunrise</li>
	 * <li>Claims for Limited Registration Period #1 (LRP1)</li>
	 * <li>Claims for Landrush</li>
	 * <li>Claims (Open)</li>
	 * <li>Custom for Limited Registration Period #2 (LRP2)</li>
	 * <li>Open</li>
	 * </ol>
	 * 
	 * @return Populated {@link EPPLaunchPolicyZone} based on the sample included
	 *         in draft-gould-regext-launch-policy.
	 */
	public static EPPLaunchPolicyZone buildLaunchPolicyZone() {
		EPPLaunchPolicyZone zone = new EPPLaunchPolicyZone();

		// Sunrise
		EPPLaunchPolicyPhase sunrise = new EPPLaunchPolicyPhase(EPPLaunchPolicyPhase.Phase.sunrise,
		      new GregorianCalendar(2017, 11, 01, 0, 0).getTime());
		sunrise.setMode(EPPLaunchPolicyPhase.Mode.pendingApplication);
		sunrise.setEndDate(new GregorianCalendar(2017, 12, 01, 0, 0).getTime());
		sunrise.setValidatePhase(true);
		sunrise.addValidatorId("tmch");
		sunrise.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.pendingAllocation));
		sunrise.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.allocated));
		sunrise.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.rejected));
		sunrise.addStatus(
		      new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.custom, "test", null, "test status"));
		sunrise.addMarkValidation(EPPLaunchPolicyPhase.MarkValidation.signedMark);
		sunrise.setMaxMarks(1);
		sunrise.addSignedMarkSupported("urn:ietf:params:xml:ns:signedMark-1.0");
		sunrise.addEncodedSignedMarkSupported("urn:ietf:params:xml:ns:signedMark-1.0");
		sunrise.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.sunrise));
		sunrise.addCreateForm(EPPLaunchPolicyPhase.CreateForm.sunrise);
		sunrise.setCreateValidateType(true);

		zone.addPhase(sunrise);

		// Claims LRP1
		EPPLaunchPolicyPhase lrp1 = new EPPLaunchPolicyPhase(EPPLaunchPolicyPhase.Phase.claims,
		      new GregorianCalendar(2017, 12, 01, 0, 0).getTime());
		lrp1.setName("lrp1");
		lrp1.setMode(EPPLaunchPolicyPhase.Mode.pendingRegistration);
		lrp1.setEndDate(new GregorianCalendar(2017, 12, 8, 0, 0).getTime());
		lrp1.setValidatePhase(true);
		lrp1.addValidatorId("tmch");
		lrp1.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.pendingValidation));
		lrp1.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.allocated));
		lrp1.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.rejected));
		lrp1.setPendingCreate(true);
		lrp1.addCheckForm(EPPLaunchPolicyPhase.CheckForm.claims);
		lrp1.addCheckForm(EPPLaunchPolicyPhase.CheckForm.availability);
		lrp1.addCheckForm(EPPLaunchPolicyPhase.CheckForm.trademark);
		lrp1.addMarkValidation(EPPLaunchPolicyPhase.MarkValidation.signedMark);
		lrp1.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.sunrise));
		lrp1.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.claims, "lrp1"));
		lrp1.addCreateForm(EPPLaunchPolicyPhase.CreateForm.claims);
		lrp1.setCreateValidateType(true);

		zone.addPhase(lrp1);

		// Claims Landrush
		EPPLaunchPolicyPhase landrush = new EPPLaunchPolicyPhase(EPPLaunchPolicyPhase.Phase.claims,
		      new GregorianCalendar(2017, 12, 8, 0, 0).getTime());
		landrush.setName("landrush");
		landrush.setMode(EPPLaunchPolicyPhase.Mode.pendingApplication);
		landrush.setEndDate(new GregorianCalendar(2017, 12, 15, 0, 0).getTime());
		landrush.setValidatePhase(true);
		landrush.addValidatorId("tmch");
		landrush.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.pendingAllocation));
		landrush.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.allocated));
		landrush.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.rejected));
		landrush.setPendingCreate(true);
		landrush.setPollPolicy(new EPPLaunchPolicyPollPolicy(false, false, false));
		landrush.addCheckForm(EPPLaunchPolicyPhase.CheckForm.claims);
		landrush.addCheckForm(EPPLaunchPolicyPhase.CheckForm.availability);
		landrush.addCheckForm(EPPLaunchPolicyPhase.CheckForm.trademark);
		landrush.addMarkValidation(EPPLaunchPolicyPhase.MarkValidation.signedMark);
		landrush.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.sunrise));
		landrush.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.claims, "lrp1"));
		landrush.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.claims, "landrush"));
		landrush.addCreateForm(EPPLaunchPolicyPhase.CreateForm.claims);
		landrush.setCreateValidateType(true);

		zone.addPhase(landrush);

		// Claims Open
		EPPLaunchPolicyPhase claims = new EPPLaunchPolicyPhase(EPPLaunchPolicyPhase.Phase.claims,
		      new GregorianCalendar(2017, 12, 15, 0, 0).getTime());
		claims.setName("open");
		claims.setMode(EPPLaunchPolicyPhase.Mode.fcfs);
		claims.setEndDate(new GregorianCalendar(2018, 2, 15, 0, 0).getTime());
		claims.setValidatePhase(true);
		claims.addValidatorId("tmch");
		claims.addCheckForm(EPPLaunchPolicyPhase.CheckForm.claims);
		claims.addCheckForm(EPPLaunchPolicyPhase.CheckForm.availability);
		claims.addCheckForm(EPPLaunchPolicyPhase.CheckForm.trademark);
		claims.addMarkValidation(EPPLaunchPolicyPhase.MarkValidation.signedMark);
		claims.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.claims, "landrush"));
		claims.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.claims, "open"));
		claims.addCreateForm(EPPLaunchPolicyPhase.CreateForm.claims);
		claims.addCreateForm(EPPLaunchPolicyPhase.CreateForm.general);
		claims.setCreateValidateType(true);

		zone.addPhase(claims);

		// Custom LRP2
		EPPLaunchPolicyPhase lrp2 = new EPPLaunchPolicyPhase(EPPLaunchPolicyPhase.Phase.custom,
		      new GregorianCalendar(2018, 2, 15, 0, 0).getTime());
		lrp2.setName("lrp2");
		lrp2.setMode(EPPLaunchPolicyPhase.Mode.pendingRegistration);
		lrp2.setEndDate(new GregorianCalendar(2018, 3, 15, 0, 0).getTime());
		lrp2.setValidatePhase(true);
		lrp2.addValidatorId("lrp2-custom");
		lrp2.addStatus(
		      new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.custom, "pendingInternalValidation"));
		lrp2.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.allocated));
		lrp2.addStatus(new EPPLaunchPolicyPhaseStatus(EPPLaunchPolicyPhaseStatus.Status.rejected));
		lrp2.setPendingCreate(true);
		lrp2.setPollPolicy(new EPPLaunchPolicyPollPolicy(true, false, false));
		lrp2.addCheckForm(EPPLaunchPolicyPhase.CheckForm.claims);
		lrp2.addCheckForm(EPPLaunchPolicyPhase.CheckForm.availability);
		lrp2.addCheckForm(EPPLaunchPolicyPhase.CheckForm.trademark);
		lrp2.addMarkValidation(EPPLaunchPolicyPhase.MarkValidation.signedMark);
		sunrise.setMaxMarks(1);
		sunrise.addSignedMarkSupported("http://www.example.com/epp/lrp2-custom-1.0");
		sunrise.addEncodedSignedMarkSupported("http://www.example.com/epp/lrp2-custom-1.0");
		lrp2.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.claims, "open"));
		lrp2.addInfoPhase(new EPPLaunchPolicyInfoPhase(EPPLaunchPolicyPhase.Phase.custom, "lrp2"));
		lrp2.addCreateForm(EPPLaunchPolicyPhase.CreateForm.sunrise);
		lrp2.addCreateForm(EPPLaunchPolicyPhase.CreateForm.general);
		lrp2.addCreateForm(EPPLaunchPolicyPhase.CreateForm.claims);
		lrp2.addCreateForm(EPPLaunchPolicyPhase.CreateForm.mixed);
		lrp2.setCreateValidateType(true);

		zone.addPhase(lrp2);

		// Open
		EPPLaunchPolicyPhase open = new EPPLaunchPolicyPhase(EPPLaunchPolicyPhase.Phase.open,
		      new GregorianCalendar(2018, 3, 15, 0, 0).getTime());
		open.setValidatePhase(false);

		zone.addPhase(open);

		return zone;
	}
}
