/*
 * Licensed to jclouds, Inc. (jclouds) under one or more
 * contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 *(Link.builder().regarding copyright ownership.  jclouds licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless(Link.builder().required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jclouds.vcloud.director.v1_5.features;

import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.CONDITION_FMT;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.CORRECT_VALUE_OBJECT_FMT;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.ENTITY_EQUAL;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.MATCHES_STRING_FMT;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.NOT_EMPTY_OBJECT_FMT;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_EQ;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY;
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.ADMIN_USER;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkControlAccessParams;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkLeaseSettingsSection;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataFor;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataKeyAbsentFor;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValue;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValueFor;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConfigSection;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkSection;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOwner;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkProductSectionList;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkStartupSection;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVApp;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.jclouds.dmtf.ovf.MsgType;
import org.jclouds.dmtf.ovf.NetworkSection;
import org.jclouds.dmtf.ovf.ProductSection;
import org.jclouds.dmtf.ovf.StartupSection;
import org.jclouds.vcloud.director.v1_5.AbstractVAppApiLiveTest;
import org.jclouds.vcloud.director.v1_5.domain.AccessSetting;
import org.jclouds.vcloud.director.v1_5.domain.Checks;
import org.jclouds.vcloud.director.v1_5.domain.Metadata;
import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
import org.jclouds.vcloud.director.v1_5.domain.Owner;
import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status;
import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.User;
import org.jclouds.vcloud.director.v1_5.domain.VApp;
import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate;
import org.jclouds.vcloud.director.v1_5.domain.Vm;
import org.jclouds.vcloud.director.v1_5.domain.network.DhcpService;
import org.jclouds.vcloud.director.v1_5.domain.network.FirewallService;
import org.jclouds.vcloud.director.v1_5.domain.network.IpRange;
import org.jclouds.vcloud.director.v1_5.domain.network.IpRanges;
import org.jclouds.vcloud.director.v1_5.domain.network.IpScope;
import org.jclouds.vcloud.director.v1_5.domain.network.NatService;
import org.jclouds.vcloud.director.v1_5.domain.network.Network;
import org.jclouds.vcloud.director.v1_5.domain.network.Network.FenceMode;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkAssignment;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConfiguration;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection.IpAddressAllocationMode;
import org.jclouds.vcloud.director.v1_5.domain.network.NetworkFeatures;
import org.jclouds.vcloud.director.v1_5.domain.network.SyslogServerSettings;
import org.jclouds.vcloud.director.v1_5.domain.network.VAppNetworkConfiguration;
import org.jclouds.vcloud.director.v1_5.domain.params.ComposeVAppParams;
import org.jclouds.vcloud.director.v1_5.domain.params.ControlAccessParams;
import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams;
import org.jclouds.vcloud.director.v1_5.domain.params.InstantiationParams;
import org.jclouds.vcloud.director.v1_5.domain.params.RecomposeVAppParams;
import org.jclouds.vcloud.director.v1_5.domain.params.SourcedCompositionItemParam;
import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams;
import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection;
import org.jclouds.vcloud.director.v1_5.domain.section.LeaseSettingsSection;
import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConfigSection;
import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.google.common.base.CharMatcher;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

/**
 * Tests behavior of the {@link VAppApi}.
 * 
 * @author grkvlt@apache.org
 */
@Test(groups = { "live", "user" }, singleThreaded = true, testName = "VAppApiLiveTest")
public class VAppApiLiveTest extends AbstractVAppApiLiveTest {

   private MetadataValue metadataValue;
   private String key;
   private boolean testUserCreated = false;
   private User user;

   @BeforeClass(alwaysRun = true)
   protected void setupRequiredEntities() {

      if (adminContext != null) {
         userUrn = adminContext.getApi().getUserApi().addUserToOrg(randomTestUser("VAppAccessTest"), org.getId())
                  .getId();
      }
      user = lazyGetUser();
   }

   @AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" })
   public void cleanUp() {
      if (adminContext != null && testUserCreated && userUrn != null) {
         try {
            adminContext.getApi().getUserApi().remove(userUrn);
         } catch (Exception e) {
            logger.warn(e, "Error when deleting user");
         }
      }
   }

   /**
    * @see VAppApi#get(URI)
    */
   @Test(description = "GET /vApp/{id}")
   public void testGetVApp() {
      // The method under test
      vApp = vAppApi.get(vAppUrn);

      // Check the retrieved object is well formed
      checkVApp(vApp);

      // Check the required fields are set
      assertEquals(vApp.isDeployed(), Boolean.FALSE,
               String.format(OBJ_FIELD_EQ, VAPP, "deployed", "FALSE", vApp.isDeployed().toString()));
      assertTrue(vApp.getName().startsWith("test-vapp-"),
               String.format(MATCHES_STRING_FMT, "name", "test-vapp-*", vApp.getName()));
      assertEquals(vApp.getDescription(), "Test VApp",
               String.format(OBJ_FIELD_EQ, VAPP, "Description", "Test VApp", vApp.getDescription()));

      // TODO instantiationParams instantiationParams()
      // TODO source.href vAppTemplateURI

      // Check status
      assertVAppStatus(vAppUrn, Status.POWERED_OFF);
   }

   @Test(description = "POST /vApp/{id}/action/recomposeVApp")
   public void testRecomposeVApp() {
      
      VApp composedVApp = vdcApi.composeVApp(vdcUrn, ComposeVAppParams.builder()
               .name(name("composed-"))
               .instantiationParams(instantiationParams())
               .build());
      
      Set<Vm> vms = getAvailableVMsFromVAppTemplate(vAppTemplate);
          
      // get the first vm to be added to vApp
      Vm toAddVm = Iterables.get(vms, 0);

      // TODO clean up network config of the vm
      //cleanUpNetworkConnectionSection(toAddVm);
      
      RecomposeVAppParams params = addRecomposeParams(composedVApp, toAddVm);

      // The method under test
      Task recomposeVApp = vAppApi.recompose(composedVApp.getId(), params);
      assertTaskSucceedsLong(recomposeVApp);

      // remove a vm
      VApp configured = vAppApi.get(composedVApp.getId());
      List<Vm> vmsToBeDeleted = configured.getChildren().getVms();
      Vm toBeDeleted = Iterables.find(vmsToBeDeleted, new Predicate<Vm>() {

         @Override
         public boolean apply(Vm vm) {
            return vm.getName().startsWith("vm-");
         }
      
      });
      Task removeVm = vmApi.remove(toBeDeleted.getId());
      assertTaskSucceedsLong(removeVm);
      
      Task deleteVApp = vAppApi.remove(composedVApp.getHref());
      assertTaskSucceedsLong(deleteVApp);
   }

   private Set<Vm> getAvailableVMsFromVAppTemplate(VAppTemplate vAppTemplate) {
      return ImmutableSet.copyOf(Iterables.filter(vAppTemplate.getChildren(), new Predicate<Vm>() {
         // filter out vms in the vApp template with computer name that contains underscores, dots,
         // or both.
         @Override
         public boolean apply(Vm input) {
            GuestCustomizationSection guestCustomizationSection = vmApi.getGuestCustomizationSection(input.getId());
            String computerName = guestCustomizationSection.getComputerName();
            String retainComputerName = CharMatcher.inRange('0', '9').or(CharMatcher.inRange('a', 'z'))
                     .or(CharMatcher.inRange('A', 'Z')).or(CharMatcher.is('-')).retainFrom(computerName);
            return computerName.equals(retainComputerName);
         }
      }));
   }

   /**
    * @see VAppApi#edit(URI, VApp)
    */
   @Test(description = "PUT /vApp/{id}", dependsOnMethods = { "testGetVApp" })
   public void testEditVApp() {
      VApp newVApp = VApp.builder().name(name("new-name-")).description("New Description").build();
      vAppNames.add(newVApp.getName());

      // The method under test
      Task editVApp = vAppApi.edit(vAppUrn, newVApp);
      assertTrue(retryTaskSuccess.apply(editVApp), String.format(TASK_COMPLETE_TIMELY, "editVApp"));

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check the required fields are set
      assertEquals(vApp.getName(), newVApp.getName(),
               String.format(OBJ_FIELD_EQ, VAPP, "Name", newVApp.getName(), vApp.getName()));
      assertEquals(vApp.getDescription(), newVApp.getDescription(),
               String.format(OBJ_FIELD_EQ, VAPP, "Description", newVApp.getDescription(), vApp.getDescription()));
   }

   @Test(description = "POST /vApp/{id}/action/deploy", dependsOnMethods = { "testGetVApp" })
   public void testDeployVApp() {
      DeployVAppParams params = DeployVAppParams.builder()
               .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
               .notPowerOn().build();

      // The method under test
      Task deployVApp = vAppApi.deploy(vAppUrn, params);
      assertTrue(retryTaskSuccessLong.apply(deployVApp), String.format(TASK_COMPLETE_TIMELY, "deployVApp"));

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check the required fields are set
      assertTrue(vApp.isDeployed(), String.format(OBJ_FIELD_EQ, VAPP, "deployed", "TRUE", vApp.isDeployed().toString()));

      // Check status
      assertVAppStatus(vAppUrn, Status.POWERED_OFF);
   }

   @Test(description = "POST /vApp/{id}/power/action/powerOn", dependsOnMethods = { "testDeployVApp" })
   public void testPowerOnVApp() {
      // Power off VApp
      vApp = powerOffVApp(vAppUrn);

      // The method under test
      Task powerOnVApp = vAppApi.powerOn(vAppUrn);
      assertTaskSucceedsLong(powerOnVApp);

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check status
      assertVAppStatus(vAppUrn, Status.POWERED_ON);
   }

   @Test(description = "POST /vApp/{id}/power/action/reboot", dependsOnMethods = { "testDeployVApp" })
   public void testReboot() {
      // Power on VApp
      vApp = powerOnVApp(vAppUrn);

      // The method under test
      Task reboot = vAppApi.reboot(vAppUrn);
      assertTaskSucceedsLong(reboot);

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check status
      assertVAppStatus(vAppUrn, Status.POWERED_OFF);
   }

   @Test(description = "POST /vApp/{id}/power/action/shutdown", dependsOnMethods = { "testDeployVApp" })
   public void testShutdown() {
      // Power on VApp
      vApp = powerOnVApp(vAppUrn);

      vApp = vAppApi.get(vAppUrn);
      
      // The method under test
      Task shutdown = vAppApi.shutdown(vAppUrn);
      assertTaskSucceedsLong(shutdown);

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check status
      assertVAppStatus(vAppUrn, Status.POWERED_OFF);

      // Power on the VApp again
      vApp = powerOnVApp(vAppUrn);
   }

   @Test(description = "POST /vApp/{id}/power/action/suspend", dependsOnMethods = { "testDeployVApp" })
   public void testSuspend() {
      // Power on VApp
      vApp = powerOnVApp(vAppUrn);

      // The method under test
      Task suspend = vAppApi.suspend(vAppUrn);
      assertTaskSucceedsLong(suspend);

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check status
      assertVAppStatus(vAppUrn, Status.SUSPENDED);

      // Power on the VApp again
      vApp = powerOnVApp(vAppUrn);
   }

   @Test(description = "POST /vApp/{id}/power/action/reset", dependsOnMethods = { "testDeployVApp" })
   public void testReset() {
      // Power on VApp
      vApp = powerOnVApp(vAppUrn);

      // The method under test
      Task reset = vAppApi.reset(vAppUrn);
      assertTaskSucceedsLong(reset);

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check status
      assertVAppStatus(vAppUrn, Status.POWERED_ON);
   }

   @Test(description = "POST /vApp/{id}/action/undeploy", dependsOnMethods = { "testDeployVApp" })
   public void testUndeployVApp() {
      // Power on VApp
      vApp = powerOnVApp(vAppUrn);

      UndeployVAppParams params = UndeployVAppParams.builder().build();

      // The method under test
      Task undeploy = vAppApi.undeploy(vAppUrn, params);
      assertTrue(retryTaskSuccess.apply(undeploy), String.format(TASK_COMPLETE_TIMELY, "undeploy"));

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check status
      assertFalse(vApp.isDeployed(),
               String.format(OBJ_FIELD_EQ, VAPP, "deployed", "FALSE", vApp.isDeployed().toString()));
      assertVAppStatus(vAppUrn, Status.POWERED_OFF);
   }

   @Test(description = "POST /vApp/{id}/power/action/powerOff", dependsOnMethods = { "testUndeployVApp" })
   public void testPowerOffVApp() {
      // Power on VApp
      vApp = powerOnVApp(vAppUrn);

      // The method under test
      Task powerOffVApp = vAppApi.powerOff(vAppUrn);
      assertTrue(retryTaskSuccess.apply(powerOffVApp), String.format(TASK_COMPLETE_TIMELY, "powerOffVApp"));

      // Get the edited VApp
      vApp = vAppApi.get(vAppUrn);

      // Check status
      assertVAppStatus(vAppUrn, Status.POWERED_OFF);
   }

   @Test(description = "POST /vApp/{id}/action/controlAccess", dependsOnMethods = { "testGetVApp" })
   public void testControlAccessUser() {
      ControlAccessParams params = ControlAccessParams
               .builder()
               .notSharedToEveryone()
               .accessSetting(
                        AccessSetting.builder()
                                 .subject(Reference.builder().href(user.getHref()).type(ADMIN_USER).build())
                                 .accessLevel("ReadOnly").build()).build();

      // The method under test
      ControlAccessParams modified = vAppApi.editControlAccess(vAppUrn, params);

      // Check the retrieved object is well formed
      checkControlAccessParams(modified);
      // Check the required fields are set
      assertEquals(modified, params, String.format(ENTITY_EQUAL, "ControlAccessParams"));
   }

   @Test(description = "POST /vApp/{id}/action/controlAccess", dependsOnMethods = { "testControlAccessUser" })
   public void testControlAccessEveryone() {

      ControlAccessParams params = ControlAccessParams.builder().sharedToEveryone().everyoneAccessLevel("FullControl")
               .build();

      // The method under test
      ControlAccessParams modified = vAppApi.editControlAccess(vAppUrn, params);

      // Check the retrieved object is well formed
      checkControlAccessParams(modified);

      // Check entities are equal
      assertEquals(modified, params, String.format(ENTITY_EQUAL, "ControlAccessParams"));
   }

   @Test(description = "POST /vApp/{id}/action/discardSuspendedState", dependsOnMethods = { "testDeployVApp" })
   public void testDiscardSuspendedState() {
      // Power on, then suspend the VApp
      vApp = powerOnVApp(vAppUrn);
      vApp = suspendVApp(vAppUrn);

      // The method under test
      Task discardSuspendedState = vAppApi.discardSuspendedState(vAppUrn);
      assertTrue(retryTaskSuccess.apply(discardSuspendedState),
               String.format(TASK_COMPLETE_TIMELY, "discardSuspendedState"));
   }

   @Test(description = "POST /vApp/{id}/action/enterMaintenanceMode", groups = { "systemAdmin" })
   public void testEnterMaintenanceMode() {

      // Do this to a new vApp, so don't mess up subsequent tests by making the vApp read-only
      VApp temp = instantiateVApp();
      DeployVAppParams params = DeployVAppParams.builder()
               .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
               .notPowerOn().build();
      Task deployVApp = vAppApi.deploy(temp.getId(), params);
      assertTaskSucceedsLong(deployVApp);

      try {
         // Method under test
         vAppApi.enterMaintenanceMode(temp.getId());

         temp = vAppApi.get(temp.getId());
         assertTrue(temp.isInMaintenanceMode(),
                  String.format(CONDITION_FMT, "InMaintenanceMode", "TRUE", temp.isInMaintenanceMode()));

         // Exit maintenance mode
         vAppApi.exitMaintenanceMode(temp.getId());
      } finally {
         cleanUpVApp(temp);
      }
   }

   @Test(description = "POST /vApp/{id}/action/exitMaintenanceMode", dependsOnMethods = { "testEnterMaintenanceMode" }, groups = { "systemAdmin" })
   public void testExitMaintenanceMode() {
      // Do this to a new vApp, so don't mess up subsequent tests by making the vApp read-only
      VApp temp = instantiateVApp();
      DeployVAppParams params = DeployVAppParams.builder()
               .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
               .notPowerOn().build();
      Task deployVApp = vAppApi.deploy(temp.getId(), params);
      assertTaskSucceedsLong(deployVApp);

      try {
         // Enter maintenance mode
         vAppApi.enterMaintenanceMode(temp.getId());

         // Method under test
         vAppApi.exitMaintenanceMode(temp.getId());

         temp = vAppApi.get(temp.getId());
         assertFalse(temp.isInMaintenanceMode(),
                  String.format(CONDITION_FMT, "InMaintenanceMode", "FALSE", temp.isInMaintenanceMode()));
      } finally {
         cleanUpVApp(temp);
      }
   }

   @Test(description = "GET /vApp/{id}/controlAccess", dependsOnMethods = { "testGetVApp" })
   public void testGetControlAccess() {
      // The method under test
      ControlAccessParams controlAccess = vAppApi.getAccessControl(vAppUrn);

      // Check the retrieved object is well formed
      checkControlAccessParams(controlAccess);
   }

   @Test(description = "GET /vApp/{id}/leaseSettingsSection", dependsOnMethods = { "testGetVApp" })
   public void testGetLeaseSettingsSection() {
      // The method under test
      LeaseSettingsSection section = vAppApi.getLeaseSettingsSection(vAppUrn);

      // Check the retrieved object is well formed
      checkLeaseSettingsSection(section);
   }

   @Test(description = "PUT /vApp/{id}/leaseSettingsSection", dependsOnMethods = { "testGetLeaseSettingsSection" })
   public void testEditLeaseSettingsSection() {
      // Copy existing section
      LeaseSettingsSection oldSection = vAppApi.getLeaseSettingsSection(vAppUrn);
      Integer twoHours = (int) TimeUnit.SECONDS.convert(2L, TimeUnit.HOURS);
      LeaseSettingsSection newSection = oldSection.toBuilder().deploymentLeaseInSeconds(twoHours).build();

      // The method under test
      Task editLeaseSettingsSection = vAppApi.editLeaseSettingsSection(vAppUrn, newSection);
      assertTrue(retryTaskSuccess.apply(editLeaseSettingsSection),
               String.format(TASK_COMPLETE_TIMELY, "editLeaseSettingsSection"));

      // Retrieve the modified section
      LeaseSettingsSection modified = vAppApi.getLeaseSettingsSection(vAppUrn);

      // Check the retrieved object is well formed
      checkLeaseSettingsSection(modified);

      // Check the date fields
      if (modified.getDeploymentLeaseExpiration() != null && newSection.getDeploymentLeaseExpiration() != null) {
         assertTrue(modified.getDeploymentLeaseExpiration().after(newSection.getDeploymentLeaseExpiration()),
                  String.format("The new deploymentLeaseExpiration timestamp must be later than the original: %s > %s",
                           dateService.iso8601DateFormat(modified.getDeploymentLeaseExpiration()),
                           dateService.iso8601DateFormat(newSection.getDeploymentLeaseExpiration())));
      }
      if (modified.getStorageLeaseExpiration() != null && newSection.getStorageLeaseExpiration() != null) {
         assertTrue(modified.getStorageLeaseExpiration().after(newSection.getStorageLeaseExpiration()), String.format(
                  "The new storageLeaseExpiration timestamp must be later than the original: %s > %s",
                  dateService.iso8601DateFormat(modified.getStorageLeaseExpiration()),
                  dateService.iso8601DateFormat(newSection.getStorageLeaseExpiration())));
      }

      // Reset the date fields
      modified = modified.toBuilder().deploymentLeaseExpiration(null).storageLeaseExpiration(null).build();
      newSection = newSection.toBuilder().deploymentLeaseExpiration(null).storageLeaseExpiration(null).build();

      // Check the section was modified correctly
      assertEquals(
               modified.getDeploymentLeaseInSeconds(),
               twoHours,
               String.format(OBJ_FIELD_EQ, "LeaseSettingsSection", "DeploymentLeaseInSeconds",
                        Integer.toString(twoHours), modified.getDeploymentLeaseInSeconds().toString()));
      assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "LeaseSettingsSection"));
   }

   @Test(description = "GET /vApp/{id}/networkConfigSection", dependsOnMethods = { "testGetVApp" })
   public void testGetNetworkConfigSection() {
      // The method under test
      NetworkConfigSection section = vAppApi.getNetworkConfigSection(vAppUrn);

      // Check the retrieved object is well formed
      checkNetworkConfigSection(section);
   }

   @Test(description = "PUT /vApp/{id}/networkConfigSection", dependsOnMethods = { "testGetNetworkConfigSection" })
   public void testEditNetworkConfigSection() {
      
      // Copy existing section and update fields
      NetworkConfigSection oldSection = vAppApi.getNetworkConfigSection(vAppUrn);
      Network network = lazyGetNetwork();
      
      tryFindBridgedNetworkInOrg();
      IpRange ipRange = ipRange();
      NetworkConfiguration newConfiguration = NetworkConfiguration.builder()
               .ipScope(ipScope(ipRange))
               .parentNetwork(Reference.builder().fromEntity(network).build())
               .fenceMode(FenceMode.NAT_ROUTED)
               .retainNetInfoAcrossDeployments(false)
               .syslogServerSettings(SyslogServerSettings.builder().syslogServerIp1("192.168.14.27").build())
               .features(NetworkFeatures.builder()
                        .service(DhcpService.builder()
                                 .ipRange(ipRange)
                                 .build())
                        .service(FirewallService.builder()
                                 .logDefaultAction(false)
                                 .defaultAction("drop")
                                 .build())
                        .service(NatService.builder()
                                 .natType("portForwarding")
                                 .enabled(false)
                                 .build())                               
                        .build())
               .build();
           
      final String networkName = name("vAppNetwork-");
      VAppNetworkConfiguration newVAppNetworkConfiguration = VAppNetworkConfiguration.builder()
               .networkName(networkName)
               .description(name("description-"))
               .configuration(newConfiguration)
               .build();

      NetworkConfigSection newSection = oldSection.toBuilder().networkConfigs(ImmutableSet.of(newVAppNetworkConfiguration)).build();

      // The method under test
      Task editNetworkConfigSection = vAppApi.editNetworkConfigSection(vAppUrn, newSection);
      assertTrue(retryTaskSuccess.apply(editNetworkConfigSection),
               String.format(TASK_COMPLETE_TIMELY, "editNetworkConfigSection"));

      // Retrieve the modified section
      NetworkConfigSection modified = vAppApi.getNetworkConfigSection(vAppUrn);

      // Check the retrieved object is well formed
      checkNetworkConfigSection(modified);
      
      Optional<VAppNetworkConfiguration> modifiedOptionalVAppNetwork = Iterables.tryFind(modified.getNetworkConfigs(), new IsVAppNetworkNamed(networkName));
      if(!modifiedOptionalVAppNetwork.isPresent())
         fail(String.format("Could not find vApp network named %s", networkName));
      
      Optional<VAppNetworkConfiguration> newOptionalVAppNetwork = Iterables.tryFind(newSection.getNetworkConfigs(), new IsVAppNetworkNamed(networkName));
      if(!newOptionalVAppNetwork.isPresent())
         fail(String.format("Could not find vApp network named %s", networkName));

      assertEquals(modifiedOptionalVAppNetwork.get().getNetworkName(), newOptionalVAppNetwork.get().getNetworkName(), String.format(ENTITY_EQUAL, "NetworkName"));
      assertEquals(modifiedOptionalVAppNetwork.get().getConfiguration().getFenceMode(), newOptionalVAppNetwork.get().getConfiguration().getFenceMode(), String.format(ENTITY_EQUAL, "FenceMode"));
      assertEquals(modifiedOptionalVAppNetwork.get().getConfiguration().getIpScope(), newOptionalVAppNetwork.get().getConfiguration().getIpScope(), String.format(ENTITY_EQUAL, "IpScope"));
      assertEquals(modifiedOptionalVAppNetwork.get().getConfiguration().getNetworkFeatures(), newOptionalVAppNetwork.get().getConfiguration().getNetworkFeatures(), String.format(ENTITY_EQUAL, "NetworkFeatures"));
   }

   private IpRange ipRange() {
      return IpRange.builder()
               .startAddress("192.168.2.100")
               .endAddress("192.168.2.199")
               .build();
   }

   private IpScope ipScope(IpRange ipRange) {
      IpRanges newIpRanges = IpRanges.builder()
               .ipRange(ipRange)
               .build();
      return IpScope.builder()
               .isInherited(false)
               .gateway("192.168.2.1")
               .netmask("255.255.0.0")
               .ipRanges(newIpRanges).build();
   }

   @Test(description = "GET /vApp/{id}/networkSection", dependsOnMethods = { "testGetVApp" })
   public void testGetNetworkSection() {
      // The method under test
      NetworkSection section = vAppApi.getNetworkSection(vAppUrn);

      // Check the retrieved object is well formed
      checkNetworkSection(section);
   }

   @Test(description = "GET /vApp/{id}/owner", dependsOnMethods = { "testGetVApp" })
   public void testGetOwner() {
      // The method under test
      Owner owner = vAppApi.getOwner(vAppUrn);

      // Check the retrieved object is well formed
      checkOwner(owner);
   }

   @Test(description = "PUT /vApp/{id}/owner", dependsOnMethods = { "testGetOwner" })
   public void testEditOwner() {
      Owner newOwner = Owner.builder().user(Reference.builder().href(user.getHref()).type(ADMIN_USER).build()).build();

      // The method under test
      vAppApi.editOwner(vAppUrn, newOwner);

      // Get the new VApp owner
      Owner modified = vAppApi.getOwner(vAppUrn);

      // Check the retrieved object is well formed
      checkOwner(modified);

      // Check the href fields match
      assertEquals(modified.getUser().getHref(), newOwner.getUser().getHref());
   }

   @Test(description = "GET /vApp/{id}/productSections", dependsOnMethods = { "testGetVApp" })
   public void testGetProductSections() {
      // The method under test
      ProductSectionList sectionList = vAppApi.getProductSections(vAppUrn);

      // Check the retrieved object is well formed
      checkProductSectionList(sectionList);
   }

   @Test(description = "PUT /vApp/{id}/productSections", dependsOnMethods = { "testGetProductSections" })
   public void testEditProductSections() {
      // Copy existing section and edit fields
      ProductSectionList oldSections = vAppApi.getProductSections(vAppUrn);
      ProductSectionList newSections = oldSections
               .toBuilder()
               .productSection(
                        ProductSection.builder().info("Information about the installed software")
                                 // Default ovf:Info text
                                 .required().product(MsgType.builder().value("jclouds").build())
                                 .vendor(MsgType.builder().value("jclouds Inc.").build())
                                 // NOTE other ProductSection elements not returned by vCloud
                                 .build()).build();

      // The method under test
      Task editProductSections = vAppApi.editProductSections(vAppUrn, newSections);
      assertTrue(retryTaskSuccess.apply(editProductSections),
               String.format(TASK_COMPLETE_TIMELY, "editProductSections"));

      // Retrieve the modified section
      ProductSectionList modified = vAppApi.getProductSections(vAppUrn);

      // Check the retrieved object is well formed
      checkProductSectionList(modified);

      // Check the modified object has an extra ProductSection
      assertEquals(modified.getProductSections().size(), oldSections.getProductSections().size() + 1);

      // Check the section was modified correctly
      assertEquals(modified, newSections);
   }

   @Test(description = "GET /vApp/{id}/startupSection", dependsOnMethods = { "testGetVApp" })
   public void testGetStartupSection() {
      // The method under test
      StartupSection section = vAppApi.getStartupSection(vAppUrn);

      // Check the retrieved object is well formed
      checkStartupSection(section);
   }

   @Test(description = "PUT /vApp/{id}/startupSection", dependsOnMethods = { "testGetStartupSection" })
   public void testEditStartupSection() {
      // Copy existing section and edit fields
      StartupSection oldSection = vAppApi.getStartupSection(vAppUrn);
      StartupSection newSection = oldSection.toBuilder().build();

      // The method under test
      Task editStartupSection = vAppApi.editStartupSection(vAppUrn, newSection);
      assertTrue(retryTaskSuccess.apply(editStartupSection), String.format(TASK_COMPLETE_TIMELY, "editStartupSection"));

      // Retrieve the modified section
      StartupSection modified = vAppApi.getStartupSection(vAppUrn);

      // Check the retrieved object is well formed
      checkStartupSection(modified);

      // Check the modified section fields are set correctly
      assertEquals(modified, newSection);
   }

   @Test(description = "PUT /vApp/{id}/metadata", dependsOnMethods = { "testGetVApp" })
   public void testSetMetadataValue() {
      key = name("key-");
      String value = name("value-");
      metadataValue = MetadataValue.builder().value(value).build();
      vAppApi.getMetadataApi(vAppUrn).putEntry(key, metadataValue);

      // Retrieve the value, and assert it was set correctly
      MetadataValue newMetadataValue = vAppApi.getMetadataApi(vAppUrn).getValue(key);

      // Check the retrieved object is well formed
      checkMetadataValueFor(VAPP, newMetadataValue, value);
   }

   @Test(description = "GET /vApp/{id}/metadata", dependsOnMethods = { "testSetMetadataValue" })
   public void testGetMetadata() {
      key = name("key-");
      String value = name("value-");
      metadataValue = MetadataValue.builder().value(value).build();
      vAppApi.getMetadataApi(vAppUrn).putEntry(key, metadataValue);

      // Call the method being tested
      Metadata metadata = vAppApi.getMetadataApi(vAppUrn).get();

      checkMetadata(metadata);

      // Check requirements for this test
      assertFalse(Iterables.isEmpty(metadata.getMetadataEntries()),
               String.format(NOT_EMPTY_OBJECT_FMT, "MetadataEntry", "vApp"));
   }

   @Test(description = "GET /vApp/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadata" })
   public void testGetOrgMetadataValue() {
      
      key = name("key-");
      String value = name("value-");
      metadataValue = MetadataValue.builder().value(value).build();
      vAppApi.getMetadataApi(vAppUrn).putEntry(key, metadataValue);
      
      // Call the method being tested
      MetadataValue newValue = vAppApi.getMetadataApi(vAppUrn).getValue(key);

      String expected = metadataValue.getValue();

      checkMetadataValue(newValue);
      assertEquals(newValue.getValue(), expected,
               String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", expected, newValue.getValue()));
   }

   @Test(description = "DELETE /vApp/{id}/metadata/{key}", dependsOnMethods = { "testSetMetadataValue" })
   public void testRemoveMetadataEntry() {
      // Delete the entry
      Task task = vAppApi.getMetadataApi(vAppUrn).removeEntry(key);
      retryTaskSuccess.apply(task);

      // Confirm the entry has been removed
      Metadata newMetadata = vAppApi.getMetadataApi(vAppUrn).get();

      // Check the retrieved object is well formed
      checkMetadataKeyAbsentFor(VAPP, newMetadata, key);
   }

   @Test(description = "POST /vApp/{id}/metadata", dependsOnMethods = { "testGetMetadata" })
   public void testMergeMetadata() {
      Metadata oldMetadata = vAppApi.getMetadataApi(vAppUrn).get();
      Map<String, String> oldMetadataMap = Checks.metadataToMap(oldMetadata);

      // Store a value, to be removed
      String key = name("key-");
      String value = name("value-");
      Metadata addedMetadata = Metadata.builder().entry(MetadataEntry.builder().key(key).value(value).build()).build();
      Task task = vAppApi.getMetadataApi(vAppUrn).merge(addedMetadata);
      retryTaskSuccess.apply(task);

      // Confirm the entry contains everything that was there, and everything that was being added
      Metadata newMetadata = vAppApi.getMetadataApi(vAppUrn).get();
      Map<String, String> expectedMetadataMap = ImmutableMap.<String, String> builder().putAll(oldMetadataMap)
               .put(key, value).build();

      // Check the retrieved object is well formed
      checkMetadataFor(VAPP, newMetadata, expectedMetadataMap);
   }

   /**
    * @see VAppApi#remove(URI)
    */
   @Test(description = "DELETE /vApp/{id}")
   public void testRemoveVApp() {
      // Create a temporary VApp to remove
      VApp temp = instantiateVApp();

      // The method under test
      Task removeVApp = vAppApi.remove(temp.getId());
      assertTrue(retryTaskSuccess.apply(removeVApp), String.format(TASK_COMPLETE_TIMELY, "removeVApp"));

      VApp removed = vAppApi.get(temp.getId());
      assertNull(removed, "The VApp " + temp.getName() + " should have been removed");
   }

   /**
    * Create the recompose vapp params.
    * 
    * @param vappTemplateRef
    * @param vdc
    * @return
    * @throws VCloudException
    */
   public RecomposeVAppParams addRecomposeParams(VApp vApp, Vm vm) {

      // creating an item element. this item will contain the vm which should be added to the vapp.
      Reference reference = Reference.builder().name(name("vm-")).href(vm.getHref()).type(vm.getType()).build();
      SourcedCompositionItemParam vmItem = SourcedCompositionItemParam.builder().source(reference).build();

      InstantiationParams vmInstantiationParams = null;

      Set<NetworkAssignment> networkAssignments = Sets.newLinkedHashSet();

      // if the vm contains a network connection and the vApp does not contain any configured
      // network
      if (vmHasNetworkConnectionConfigured(vm)) {
         if (!vAppHasNetworkConfigured(vApp)) {
            // add a new network connection section for the vm.
            NetworkConnectionSection networkConnectionSection = NetworkConnectionSection.builder()
                     .info("Empty network configuration parameters").build();
            // adding the network connection section to the instantiation params of the vapp.
            vmInstantiationParams = InstantiationParams.builder().sections(ImmutableSet.of(networkConnectionSection))
                     .build();
         }

         // if the vm already contains a network connection section and if the vapp contains a
         // configured network -> vm could be mapped to that network.
         else {
            Set<VAppNetworkConfiguration> vAppNetworkConfigurations = listVappNetworkConfigurations(vApp);
            for (VAppNetworkConfiguration vAppNetworkConfiguration : vAppNetworkConfigurations) {
               NetworkAssignment networkAssignment = NetworkAssignment.builder()
                        .innerNetwork(vAppNetworkConfiguration.getNetworkName())
                        .containerNetwork(vAppNetworkConfiguration.getNetworkName()).build();
               networkAssignments.add(networkAssignment);
            }
         }
      }

      // if the vm does not contain any network connection sections and if the
      // vapp contains a network configuration. we should add the vm to this
      // vapp network
      else {
         if (vAppHasNetworkConfigured(vApp)) {
            VAppNetworkConfiguration vAppNetworkConfiguration = getVAppNetworkConfig(vApp);
            NetworkConnection networkConnection = NetworkConnection.builder()
                     .network(vAppNetworkConfiguration.getNetworkName())
                     .ipAddressAllocationMode(IpAddressAllocationMode.DHCP).build();

            NetworkConnectionSection networkConnectionSection = NetworkConnectionSection.builder().info("networkInfo")
                     .primaryNetworkConnectionIndex(0).networkConnection(networkConnection).build();

            // adding the network connection section to the instantiation params of the vapp.
            vmInstantiationParams = InstantiationParams.builder().sections(ImmutableSet.of(networkConnectionSection))
                     .build();
         }
      }

      if (vmInstantiationParams != null)
         vmItem = SourcedCompositionItemParam.builder().fromSourcedCompositionItemParam(vmItem)
                  .instantiationParams(vmInstantiationParams).build();

      if (networkAssignments != null)
         vmItem = SourcedCompositionItemParam.builder().fromSourcedCompositionItemParam(vmItem)
                  .networkAssignment(networkAssignments).build();

      return RecomposeVAppParams.builder().name(name("recompose-"))
      // adding the vm item.
               .sourcedItems(ImmutableList.of(vmItem)).build();
   }
   
   private final class IsVAppNetworkNamed implements Predicate<VAppNetworkConfiguration> {
      private final String networkName;

      private IsVAppNetworkNamed(String networkName) {
         this.networkName = networkName;
      }

      @Override
      public boolean apply(VAppNetworkConfiguration input) {
         return input.getNetworkName().equals(networkName);
      }
   }
   
   private void cleanUpNetworkConnectionSection(Vm toAddVm) {
      NetworkConnectionSection networkConnectionSection = vmApi.getNetworkConnectionSection(toAddVm.getId());
      Set<NetworkConnection> networkConnections = networkConnectionSection.getNetworkConnections();
      for (NetworkConnection networkConnection : networkConnections) {
         NetworkConnection newNetworkConnection = networkConnection.toBuilder().isConnected(false).build();
         networkConnectionSection = networkConnectionSection.toBuilder().networkConnection(newNetworkConnection)
                  .build();
      }

      Task configureNetwork = vmApi.editNetworkConnectionSection(toAddVm.getId(), networkConnectionSection);
      assertTaskSucceedsLong(configureNetwork);
   }

}
