/***********************************************************
Copyright (C) 2021 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.maintenance.v1_0;

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.EPPMsgQueue;
import com.verisign.epp.codec.gen.EPPResult;
import com.verisign.epp.codec.gen.EPPTransId;
import com.verisign.epp.util.TestThread;

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

/**
 * Is a unit test of the com.verisign.epp.codec.maintenance package.
 */
public class EPPMaintenanceTst extends TestCase {
	/**
	 * Number of unit test iterations to run. This is set in
	 * {@code EPPCodecTst.main}
	 */
	static private long numIterations = 1;

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

	/**
	 * Unit test of the Maintenance Info Command with Identifier.
	 */
	public void testInfoCommandId() {
		EPPCodecTst.printStart("testInfoCommandId");

		EPPEncodeDecodeStats theStats;

		// Maintenance notification identifier test
		EPPMaintenanceInfoCmd theCommand = new EPPMaintenanceInfoCmd("ABC-12345", "2e6df9b0-4092-4491-bcc8-9fb2166dcee6");
		theStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(theStats);

		EPPCodecTst.printEnd("testInfoCommandId");
	}

	/**
	 * Unit test of the Maintenance Info Command with List.
	 */
	public void testInfoCommandList() {
		EPPCodecTst.printStart("testInfoCommandList");

		EPPEncodeDecodeStats theStats;

		// Maintenance notification identifier test
		EPPMaintenanceInfoCmd theCommand = new EPPMaintenanceInfoCmd("ABC-12345");
		theStats = EPPCodecTst.testEncodeDecode(theCommand);
		System.out.println(theStats);

		EPPCodecTst.printEnd("testInfoCommandList");
	}

	/**
	 * Unit test of the Maintenance Info Response with Id.
	 */
	public void testInfoResponseId() {
		EPPCodecTst.printStart("testInfoResponseId");

		EPPEncodeDecodeStats theStats;

		EPPTransId theTransId = new EPPTransId("ABC-12345", "54321-XYZ");

		// TEST - Maintenance based on sample in draft
		EPPMaintenanceItem theMaintenance = new EPPMaintenanceItem();
		theMaintenance.setMaintenanceId(new EPPMaintenanceId("2e6df9b0-4092-4491-bcc8-9fb2166dcee6"));
		theMaintenance
		      .addSystem(new EPPMaintenanceSystem("EPP", "epp.registry.example", EPPMaintenanceSystem.Impact.full));
		theMaintenance.setEnvironment(EPPMaintenanceItem.Environment.production);
		theMaintenance.setStartDate(new GregorianCalendar(2021, 9, 30, 6, 00).getTime());
		theMaintenance.setEndDate(new GregorianCalendar(2021, 9, 30, 14, 25, 57).getTime());
		theMaintenance.setReason(EPPMaintenanceItem.Reason.planned);
		theMaintenance.setDetail("https://www.registry.example/notice?123");
		theMaintenance
		      .addDescription(new EPPMaintenanceDescription("free text", EPPMaintenanceDescription.Type.plain, "en"));
		theMaintenance
		      .addDescription(new EPPMaintenanceDescription("Freitext", EPPMaintenanceDescription.Type.plain, "de"));
		theMaintenance.addTld("example");
		theMaintenance.addTld("test");
		theMaintenance.setIntervention(new EPPMaintenanceIntervention(false, false));
		theMaintenance.setCreatedDate(new GregorianCalendar(2021, 3, 8, 22, 10).getTime());

		EPPMaintenanceInfoResp theResp = new EPPMaintenanceInfoResp(theTransId, theMaintenance);

		theStats = EPPCodecTst.testEncodeDecode(theResp);
		System.out.println(theStats);

		// TEST - Maintenance extended from sample in draft to include all
		// attributes.
		theMaintenance = new EPPMaintenanceItem();
		theMaintenance.setMaintenanceId(new EPPMaintenanceId("2e6df9b0-4092-4491-bcc8-9fb2166dcee6", "test name", null));
		theMaintenance.addType(new EPPMaintenanceType("Routine Maintenance"));
		theMaintenance
		      .addSystem(new EPPMaintenanceSystem("EPP", "all.registry.example", EPPMaintenanceSystem.Impact.partial));
		theMaintenance.setEnvironment(EPPMaintenanceItem.Environment.custom);
		theMaintenance.setCustomEnvironment("customEnv");
		theMaintenance.setStartDate(new GregorianCalendar(2021, 9, 30, 6, 00).getTime());
		theMaintenance.setEndDate(new GregorianCalendar(2021, 9, 30, 14, 25, 57).getTime());
		theMaintenance.setReason(EPPMaintenanceItem.Reason.planned);
		theMaintenance.setDetail("https://www.registry.example/notice?123");
		theMaintenance.addDescription(new EPPMaintenanceDescription(
		      "<!DOCTYPE html>\n" + "<html>\n" + "<body>\n" + "\n" + "<h1>My First Heading</h1>\n"
		            + "<p>My first paragraph.</p>\n" + "\n" + "</body>\n" + "</html>",
		      EPPMaintenanceDescription.Type.html, EPPMaintenanceDescription.DEFAULT_LANG));
		theMaintenance.addTld("example");
		theMaintenance.addTld("test");
		theMaintenance.setIntervention(new EPPMaintenanceIntervention(false, false));
		theMaintenance.setCreatedDate(new GregorianCalendar(2021, 3, 8, 22, 10).getTime());
		theMaintenance.setLastUpdatedDate(new GregorianCalendar(2021, 10, 5, 20, 50).getTime());

		theResp = new EPPMaintenanceInfoResp(theTransId, theMaintenance);

		theStats = EPPCodecTst.testEncodeDecode(theResp);
		System.out.println(theStats);

		// TEST - Minimal maintenance with only the required attributes.
		theMaintenance = new EPPMaintenanceItem();
		theMaintenance.setMaintenanceId(new EPPMaintenanceId("2e6df9b0-4092-4491-bcc8-9fb2166dcee6"));
		theMaintenance
		      .addSystem(new EPPMaintenanceSystem("EPP", "min.registry.example", EPPMaintenanceSystem.Impact.partial));
		theMaintenance.setEnvironment(EPPMaintenanceItem.Environment.ote);
		theMaintenance.setStartDate(new GregorianCalendar(2021, 9, 30, 6, 00).getTime());
		theMaintenance.setEndDate(new GregorianCalendar(2021, 9, 30, 14, 25, 57).getTime());
		theMaintenance.setReason(EPPMaintenanceItem.Reason.planned);
		theMaintenance.addTld("example");
		theMaintenance.addTld("test");
		theMaintenance.setIntervention(new EPPMaintenanceIntervention(false, false));
		theMaintenance.setCreatedDate(new GregorianCalendar(2021, 3, 8, 22, 10).getTime());

		theResp = new EPPMaintenanceInfoResp(theTransId, theMaintenance);

		theStats = EPPCodecTst.testEncodeDecode(theResp);
		System.out.println(theStats);

		EPPCodecTst.printEnd("testInfoResponseId");
	}

	/**
	 * Unit test of the Maintenance Poll Response
	 */
	public void testPollResponse() {
		EPPCodecTst.printStart("testPollResponse");

		EPPEncodeDecodeStats theStats;

		EPPTransId theTransId = new EPPTransId("ABC-12345", "54321-XYZ");

		// TEST - Maintenance Poll Response for a Registry Maintenance
		// Notification of type create.
		EPPMaintenanceItem theMaintenance = new EPPMaintenanceItem();
		theMaintenance.setMaintenanceId(new EPPMaintenanceId("2e6df9b0-4092-4491-bcc8-9fb2166dcee6"));
		theMaintenance.setPollType(EPPMaintenanceItem.PollType.create);
		theMaintenance
		      .addSystem(new EPPMaintenanceSystem("EPP", "epp.registry.example", EPPMaintenanceSystem.Impact.full));
		theMaintenance.setEnvironment(EPPMaintenanceItem.Environment.production);
		theMaintenance.setStartDate(new GregorianCalendar(2021, 9, 30, 6, 00).getTime());
		theMaintenance.setEndDate(new GregorianCalendar(2021, 9, 30, 14, 25, 57).getTime());
		theMaintenance.setReason(EPPMaintenanceItem.Reason.planned);
		theMaintenance.setDetail("https://www.registry.example/notice?123");
		theMaintenance
		      .addDescription(new EPPMaintenanceDescription("free text", EPPMaintenanceDescription.Type.plain, "en"));
		theMaintenance
		      .addDescription(new EPPMaintenanceDescription("Freitext", EPPMaintenanceDescription.Type.plain, "de"));
		theMaintenance.addTld("example");
		theMaintenance.addTld("test");
		theMaintenance.setIntervention(new EPPMaintenanceIntervention(false, false));
		theMaintenance.setCreatedDate(new GregorianCalendar(2021, 3, 8, 22, 10).getTime());

		EPPMaintenanceInfoResp theResp = new EPPMaintenanceInfoResp(theTransId, theMaintenance);
		theResp.setMsgQueue(new EPPMsgQueue(1L, "12345", new GregorianCalendar(2021, 2, 8, 22, 10).getTime(),
		      "Registry Maintenance Notification"));
		theResp.setResult(EPPResult.SUCCESS_POLL_MSG);

		theStats = EPPCodecTst.testEncodeDecode(theResp);
		System.out.println(theStats);

		EPPCodecTst.printEnd("testPollResponse");
	}

	/**
	 * Unit test of the Maintenance Info Response with List.
	 */
	public void testInfoResponseList() {
		EPPCodecTst.printStart("testInfoResponseList");

		EPPEncodeDecodeStats theStats;

		EPPTransId theTransId = new EPPTransId("ABC-12345", "54321-XYZ");

		// TEST - maintenance list items

		EPPMaintenanceInfoResp theResp = new EPPMaintenanceInfoResp(theTransId);
		EPPMaintenanceListItem theItem = new EPPMaintenanceListItem(
		      new EPPMaintenanceId("2e6df9b0-4092-4491-bcc8-9fb2166dcee6"),
		      new GregorianCalendar(2021, 02, 8, 22, 10).getTime(), new GregorianCalendar(2021, 04, 30, 6, 0).getTime(),
		      new GregorianCalendar(2021, 04, 30, 7, 0).getTime(), null);
		theResp.addListItem(theItem);
		theItem = new EPPMaintenanceListItem(new EPPMaintenanceId("91e9dabf-c4e9-4c19-a56c-78e3e89c2e2f"),
		      new GregorianCalendar(2021, 6, 15, 4, 30).getTime(), new GregorianCalendar(2021, 6, 15, 5, 30).getTime(),
		      new GregorianCalendar(2021, 02, 8, 22, 10).getTime(), new GregorianCalendar(2021, 03, 8, 20, 11).getTime());
		theResp.addListItem(theItem);

		theStats = EPPCodecTst.testEncodeDecode(theResp);
		System.out.println(theStats);

		EPPCodecTst.printEnd("testInfoResponseList");
	}

	/**
	 * JUNIT {@code setUp} method, which sets the default client Id to
	 * "theRegistrar" and initializes the {@code EPPMaintenanceMapFactory} 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 EPPMaintenanceTst}.
	 *
	 * @return Tests to run
	 */
	public static Test suite() {
		EPPCodecTst.initEnvironment();

		TestSuite suite = new TestSuite(EPPMaintenanceTst.class);

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

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

		// Add the EPPMaintenanceMapFactory to the EPPCodec.
		try {
			EPPFactory.getInstance().addMapFactory("com.verisign.epp.codec.maintenance.v1_0.EPPMaintenanceMapFactory");
		}
		catch (EPPCodecException e) {
			Assert.fail("EPPCodecException adding factories 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 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("EPPMaintenanceTst Thread " + i, EPPMaintenanceTst.suite());
				thread.start();
			}
		}
		else { // Single threaded mode.
			junit.textui.TestRunner.run(EPPMaintenanceTst.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;
	}

}
