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

import java.util.GregorianCalendar;
import java.util.Vector;

import com.verisign.epp.codec.domain.EPPDomainCreateCmd;
import com.verisign.epp.codec.domain.EPPDomainInfoCmd;
import com.verisign.epp.codec.domain.EPPDomainInfoResp;
import com.verisign.epp.codec.domain.EPPDomainPeriod;
import com.verisign.epp.codec.domain.EPPDomainStatus;
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.EPPEncodeDecodeStats;
import com.verisign.epp.codec.gen.EPPFactory;
import com.verisign.epp.codec.gen.EPPResult;
import com.verisign.epp.codec.gen.EPPTransId;
import com.verisign.epp.codec.host.EPPHostAddress;
import com.verisign.epp.codec.host.EPPHostCreateCmd;
import com.verisign.epp.codec.host.EPPHostInfoCmd;
import com.verisign.epp.codec.host.EPPHostInfoResp;
import com.verisign.epp.codec.host.EPPHostStatus;
import com.verisign.epp.codec.host.EPPHostUpdateCmd;
import com.verisign.epp.codec.secdnsext.v11.EPPSecDNSAlgorithm;
import com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtCreate;
import com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtDsData;
import com.verisign.epp.util.TestThread;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Is a unit test of the {@code com.verisign.epp.codec.ttl.v1_0} package. The unit test
 * will execute, gather statistics, and output the results of a test of each
 * c{@code com.verisign.epp.codec.ttl.v1_0} package concrete extension
 * {@code EPPCodecComponent}'s.
 */
public class EPPTtlTst {

  /**
   * Unit test for the extension to the create command.
   */
  @Test
  public void testDomainCreate() {
    EPPDomainCreateCmd theCommand;
    EPPEncodeDecodeStats commandStats;

    EPPCodecTst.printStart("testDomainCreate");

    // Domain Create Command
    theCommand = new EPPDomainCreateCmd("ABC-12345", "example.com", new EPPAuthInfo(""));

    theCommand.setPeriod(new EPPDomainPeriod(1));

    Vector<String> servers = new Vector<String>();
    servers.add("ns1.example.com");
    servers.add("ns1.example.net");
    theCommand.setServers(servers);

    // TTL Extension
    EPPTtlCreate theTtlExt = new EPPTtlCreate();
    theTtlExt.addTtl(new EPPTtl(RRecType.NS, 172800));
    theTtlExt.addTtl(new EPPTtl(RRecType.DS, 300));
    theTtlExt.addTtl(new EPPTtl(RRecType.CUSTOM, "DELEG", 3600));
    theCommand.addExtension(theTtlExt);

    // DNSSEC Extension
    EPPSecDNSExtCreate theDnssecExt = new EPPSecDNSExtCreate();

    theDnssecExt.appendDsData(new EPPSecDNSExtDsData(12345, EPPSecDNSAlgorithm.ECDSAP256SHA256,
          EPPSecDNSExtDsData.SHA256_DIGEST_TYPE, "49FD46E6C4B45C55D4AC"));

    theCommand.addExtension(theDnssecExt);

    // Encode Domain Create Command
    commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPCodecTst.printEnd("testDomainCreate");
  }

  /**
   * Unit test for the extension to the host command.
   */
  @Test
  public void testHostCreate() {
    EPPHostCreateCmd theCommand;
    EPPEncodeDecodeStats commandStats;

    EPPCodecTst.printStart("testHostCreate");

    // Host Create Command
    theCommand = new EPPHostCreateCmd("ABC-12345", "ns1.example.com");

    Vector addresses = new Vector();
    addresses.addElement(new EPPHostAddress("192.0.2.2", EPPHostAddress.IPV4));
    addresses.addElement(new EPPHostAddress("1080::8:800:200C:417A", EPPHostAddress.IPV6));
    theCommand.setAddresses(addresses);

    // TTL Extension
    EPPTtlCreate theCreateExt = new EPPTtlCreate();
    theCreateExt.addTtl(new EPPTtl(RRecType.A));
    theCreateExt.addTtl(new EPPTtl(RRecType.AAAA, 86400));
    theCommand.addExtension(theCreateExt);

    // Encode Host Create Command
    commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPCodecTst.printEnd("testHostCreate");
  }

  /**
   * Unit test for the extension to the domain update command.
   */
  @Test
  public void testDomainUpdate() {

    EPPCodecTst.printStart("testDomainUpdate");

    // Domain Update Command
    EPPDomainUpdateCmd theCommand = new EPPDomainUpdateCmd("ABC-12345", "example.com", null, null, null);

    // TTL Extension
    EPPTtlUpdate theUpdateExt = new EPPTtlUpdate();
    theUpdateExt.addTtl(new EPPTtl(RRecType.NS));
    theCommand.addExtension(theUpdateExt);

    // Encode Domain Update Command
    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPCodecTst.printEnd("testDomainUpdate");
  }

  /**
   * Unit test for the extension to the host update command.
   */
  @Test
  public void testHostUpdate() {

    EPPCodecTst.printStart("testHostUpdate");

    // Host Update Command
    EPPHostUpdateCmd theCommand = new EPPHostUpdateCmd("ABC-12345", "ns1.example.com", null, null, null);

    // TTL Extension
    EPPTtlUpdate theUpdateExt = new EPPTtlUpdate();
    theUpdateExt.addTtl(new EPPTtl(RRecType.A, 86400));
    theUpdateExt.addTtl(new EPPTtl(RRecType.AAAA, 3600));
    theCommand.addExtension(theUpdateExt);

    // Encode Host Update Command
    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theCommand);
    System.out.println(commandStats);

    EPPCodecTst.printEnd("testHostUpdate");
  }

  /**
   * Unit test for the extension to the domain info command.
   */
  @Test
  public void testDomainInfo() {

    EPPCodecTst.printStart("testDomainInfo");

    // Info command with use of default policy of false
    EPPDomainInfoCmd theCommand;
    theCommand = new EPPDomainInfoCmd(null, "example.com");
    theCommand.addExtension(new EPPTtlInfo());

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

    // Info command with use of explicit "false" policy
    theCommand = new EPPDomainInfoCmd(null, "example.com");
    theCommand.addExtension(new EPPTtlInfo());

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

    // Info command with use of "true" policy
    theCommand = new EPPDomainInfoCmd(null, "example.com");
    theCommand.addExtension(new EPPTtlInfo(true));

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

  /**
   * Unit test for the extension to the domain info response.
   */
  @Test
  public void testDomainInfoResponse() {

    EPPCodecTst.printStart("testDomainInfoResponse");

    // Domain Info Response with Default Mode
    Vector<EPPDomainStatus> statuses = new Vector<EPPDomainStatus>();
    statuses.addElement(new EPPDomainStatus(EPPDomainStatus.ELM_STATUS_OK));

    EPPTransId respTransId = new EPPTransId("ABC-12345", "54321-XYZ");
    EPPDomainInfoResp theResponse = new EPPDomainInfoResp(respTransId, "EXAMPLE1-REP", "example.com", "ClientX",
          statuses, "ClientX", new GregorianCalendar(2023, 11, 8, 10, 14, 55).getTime(), null);

    Vector<String> servers = new Vector<String>();
    servers.add("ns1.example.com");
    servers.add("ns1.example.net");
    theResponse.setNses(servers);

    theResponse.setExpirationDate(new GregorianCalendar(2024, 11, 8, 10, 14, 55).getTime());

    theResponse.setResult(EPPResult.SUCCESS);

    // TTL Extension
    EPPTtlInfData theInfExt = new EPPTtlInfData();
    theInfExt.addTtl(new EPPTtl(RRecType.NS, 172800));
    theInfExt.addTtl(new EPPTtl(RRecType.DS, 300));
    theResponse.addExtension(theInfExt);

    // DNSSEC Extension
    EPPSecDNSExtCreate theDnssecExt = new EPPSecDNSExtCreate();

    theDnssecExt.appendDsData(new EPPSecDNSExtDsData(12345, EPPSecDNSAlgorithm.ECDSAP256SHA256,
          EPPSecDNSExtDsData.SHA256_DIGEST_TYPE, "49FD46E6C4B45C55D4AC"));

    theResponse.addExtension(theDnssecExt);

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

    // Domain Info Response with Policy Mode
    statuses = new Vector<EPPDomainStatus>();
    statuses.addElement(new EPPDomainStatus(EPPDomainStatus.ELM_STATUS_OK));

    respTransId = new EPPTransId("ABC-12345", "54321-XYZ");
    theResponse = new EPPDomainInfoResp(respTransId, "EXAMPLE1-REP", "example.com", "ClientX",
          statuses, "ClientX", new GregorianCalendar(2023, 11, 8, 10, 14, 55).getTime(), null);

    servers = new Vector<String>();
    servers.add("ns1.example.com");
    servers.add("ns1.example.net");
    theResponse.setNses(servers);

    theResponse.setExpirationDate(new GregorianCalendar(2024, 11, 8, 10, 14, 55).getTime());

    theResponse.setResult(EPPResult.SUCCESS);

    // TTL Extension
    theInfExt = new EPPTtlInfData();
    theInfExt.addTtl(new EPPTtl(RRecType.NS, null, 3600, 172800, 86400, 172800));
    theInfExt.addTtl(new EPPTtl(RRecType.DS, null, 60, 172800, 86400, 300));
    theResponse.addExtension(theInfExt);

    // DNSSEC Extension
    theDnssecExt = new EPPSecDNSExtCreate();

    theDnssecExt.appendDsData(new EPPSecDNSExtDsData(12345, EPPSecDNSAlgorithm.ECDSAP256SHA256,
          EPPSecDNSExtDsData.SHA256_DIGEST_TYPE, "49FD46E6C4B45C55D4AC"));

    theResponse.addExtension(theDnssecExt);

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

    EPPCodecTst.printEnd("testDomainInfoResponse");
  }

  /**
   * Unit test for the extension to the host info command.
   */
  @Test
  public void testHostInfo() {

    EPPCodecTst.printStart("testHostInfo");

    // Info command with use of default policy of false
    EPPHostInfoCmd theCommand;
    theCommand = new EPPHostInfoCmd(null, "ns1.example.com");
    theCommand.addExtension(new EPPTtlInfo());

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

    // Info command with use of explicit "false" policy
    theCommand = new EPPHostInfoCmd(null, "ns1.example.com");
    theCommand.addExtension(new EPPTtlInfo());

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

    // Info command with use of "true" policy
    theCommand = new EPPHostInfoCmd(null, "ns1.example.com");
    theCommand.addExtension(new EPPTtlInfo(true));

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

  /**
   * Unit test for the extension to the host info response.
   */
  @Test
  public void testHostInfoResponse() {

    EPPCodecTst.printStart("testHostInfoResponse");

    // Host Info Response with Default Mode
    EPPTransId respTransId = new EPPTransId("ABC-12345", "54321-XYZ");
    EPPHostInfoResp theResponse = new EPPHostInfoResp(respTransId, "n1.example.com", "NS1_EXAMPLE1-REP",
          new EPPHostStatus(EPPHostStatus.ELM_STATUS_OK), "ClientX", "ClientX",
          new GregorianCalendar(2023, 11, 8, 10, 14, 55).getTime());

    Vector addresses = new Vector();
    addresses.addElement(new EPPHostAddress("192.0.2.2", EPPHostAddress.IPV4));
    addresses.addElement(new EPPHostAddress("1080::8:800:200C:417A", EPPHostAddress.IPV6));
    theResponse.setAddresses(addresses);

    theResponse.setResult(EPPResult.SUCCESS);

    // TTL Extension
    EPPTtlInfData theInfExt = new EPPTtlInfData();
    theInfExt.addTtl(new EPPTtl(RRecType.A, 172800));
    theInfExt.addTtl(new EPPTtl(RRecType.AAAA, 86400));
    theResponse.addExtension(theInfExt);

    // Encode Host Info Response
    EPPEncodeDecodeStats commandStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(commandStats);

    // Host Info Response with Policy Mode
    respTransId = new EPPTransId("ABC-12345", "54321-XYZ");
    theResponse = new EPPHostInfoResp(respTransId, "n1.example.com", "NS1_EXAMPLE1-REP",
          new EPPHostStatus(EPPHostStatus.ELM_STATUS_OK), "ClientX", "ClientX",
          new GregorianCalendar(2023, 11, 8, 10, 14, 55).getTime());

    addresses = new Vector();
    addresses.addElement(new EPPHostAddress("192.0.2.2", EPPHostAddress.IPV4));
    addresses.addElement(new EPPHostAddress("1080::8:800:200C:417A", EPPHostAddress.IPV6));
    theResponse.setAddresses(addresses);

    theResponse.setResult(EPPResult.SUCCESS);

    // TTL Extension
    theInfExt = new EPPTtlInfData();
    theInfExt.addTtl(new EPPTtl(RRecType.A, null, 3600, 172800, 86400, 172800));
    theInfExt.addTtl(new EPPTtl(RRecType.AAAA, null, 3600, 172800, 86400, 86400));
    theResponse.addExtension(theInfExt);

    // Encode Host Info Response
    commandStats = EPPCodecTst.testEncodeDecode(theResponse);
    System.out.println(commandStats);

    EPPCodecTst.printEnd("testHostInfoResponse");
  }

  /**
   * JUNIT {@code suite} static method, which returns the tests associated
   * with {@code EPPTtlTst}.
   *
   */
  @BeforeClass
  public static void setup() {
    EPPCodecTst.initEnvironment();

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

    // Add the EPPNSProductExtFactory to the EPPCodec.
    try {
      EPPFactory.getInstance().addMapFactory("com.verisign.epp.codec.host.EPPHostMapFactory");
      EPPFactory.getInstance().addMapFactory("com.verisign.epp.codec.domain.EPPDomainMapFactory");
      EPPFactory.getInstance().addExtFactory("com.verisign.epp.codec.ttl.v1_0.EPPTtlExtFactory");
      EPPFactory.getInstance().addExtFactory("com.verisign.epp.codec.secdnsext.v11.EPPSecDNSExtFactory");
    }
    catch (EPPCodecException e) {
      Assert.fail("EPPCodecException adding factories to EPPCodec: " + e);
    }
  }

}
