/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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 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.softlayer.compute.strategy;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.tryFind;
import static java.lang.Math.round;
import static java.lang.String.format;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.jclouds.compute.util.ComputeServiceUtils.getSpace;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_ACTIVE_TRANSACTIONS_DELAY;
import static org.jclouds.softlayer.reference.SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY;
import static org.jclouds.util.Predicates2.retry;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.Volume.Type;
import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;
import org.jclouds.softlayer.SoftLayerApi;
import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.jclouds.softlayer.domain.ContainerVirtualGuestConfiguration;
import org.jclouds.softlayer.domain.Datacenter;
import org.jclouds.softlayer.domain.NetworkVlan;
import org.jclouds.softlayer.domain.OperatingSystem;
import org.jclouds.softlayer.domain.Password;
import org.jclouds.softlayer.domain.SecuritySshKey;
import org.jclouds.softlayer.domain.SoftwareDescription;
import org.jclouds.softlayer.domain.SoftwareLicense;
import org.jclouds.softlayer.domain.VirtualDiskImage;
import org.jclouds.softlayer.domain.VirtualDiskImageSoftware;
import org.jclouds.softlayer.domain.VirtualGuest;
import org.jclouds.softlayer.domain.VirtualGuestAttribute;
import org.jclouds.softlayer.domain.VirtualGuestBlockDevice;
import org.jclouds.softlayer.domain.VirtualGuestBlockDeviceTemplate;
import org.jclouds.softlayer.domain.VirtualGuestBlockDeviceTemplateGroup;
import org.jclouds.softlayer.domain.VirtualGuestNetworkComponent;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;

/**
 * defines the connection between the {@link SoftLayerApi} implementation and
 * the jclouds {@link org.jclouds.compute.ComputeService}
 *
 */
@Singleton
public class SoftLayerComputeServiceAdapter implements
      ComputeServiceAdapter<VirtualGuest, Hardware, OperatingSystem, Datacenter> {

   private static final String USER_META_NOTES = "notes";
   private static final int USER_META_NOTES_MAX_LENGTH = 1000;
   private static final String BOOTABLE_DEVICE = "0";
   public static final String DEFAULT_DISK_TYPE = "LOCAL";

   @Resource
   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
   protected Logger logger = Logger.NULL;

   private final SoftLayerApi api;
   private final Supplier<ContainerVirtualGuestConfiguration> createObjectOptionsSupplier;
   private final Predicate<VirtualGuest> loginDetailsTester;
   private final long guestLoginDelay;
   private final long activeTransactionsDelay;

   @Inject
   public SoftLayerComputeServiceAdapter(SoftLayerApi api,
         VirtualGuestHasLoginDetailsPresent virtualGuestHasLoginDetailsPresent,
         @Memoized Supplier<ContainerVirtualGuestConfiguration> createObjectOptionsSupplier,
         @Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY) long guestLoginDelay,
         @Named(PROPERTY_SOFTLAYER_VIRTUALGUEST_ACTIVE_TRANSACTIONS_DELAY) long activeTransactionsDelay) {
      this.api = checkNotNull(api, "api");
      this.guestLoginDelay = guestLoginDelay;
      this.activeTransactionsDelay = activeTransactionsDelay;
      this.createObjectOptionsSupplier = checkNotNull(createObjectOptionsSupplier, "createObjectOptionsSupplier");
      checkArgument(guestLoginDelay > 500, "guestOrderDelay must be in milliseconds and greater than 500");
      this.loginDetailsTester = retry(virtualGuestHasLoginDetailsPresent, guestLoginDelay);
   }

   @Override
   public NodeAndInitialCredentials<VirtualGuest> createNodeWithGroupEncodedIntoName(String group, String name,
         Template template) {
      checkNotNull(template, "template was null");
      checkNotNull(template.getOptions(), "template options was null");
      checkArgument(template.getOptions().getClass().isAssignableFrom(SoftLayerTemplateOptions.class),
              "options class %s should have been assignable from SoftLayerTemplateOptions",
              template.getOptions().getClass());

      SoftLayerTemplateOptions templateOptions = template.getOptions().as(SoftLayerTemplateOptions.class);
      String domainName = templateOptions.getDomainName();
      String diskType = templateOptions.getDiskType() == null ? DEFAULT_DISK_TYPE : templateOptions.getDiskType();
      boolean hourlyBillingFlag = templateOptions.isHourlyBillingFlag()  == null ? true : templateOptions.isHourlyBillingFlag();
      Integer portSpeed = templateOptions.getPortSpeed();
      Set<VirtualGuestNetworkComponent> networkComponents = portSpeed != null ?
              ImmutableSet.of(VirtualGuestNetworkComponent.builder().speed(portSpeed).build()) :
              ImmutableSet.<VirtualGuestNetworkComponent>of();
      final Datacenter datacenter = Datacenter.builder().name(template.getLocation().getId()).build();
      final String imageId = template.getImage().getId();
      int cores = (int) template.getHardware().getProcessors().get(0).getCores();
      String notes = getNotes(templateOptions);

      VirtualGuest.Builder<?> virtualGuestBuilder = VirtualGuest.builder()
              .domain(domainName)
              .hostname(name)
              .hourlyBillingFlag(hourlyBillingFlag)
              .startCpus(cores)
              .maxMemory(template.getHardware().getRam())
              .datacenter(datacenter)
              .localDiskFlag(isLocalDisk(diskType))
              .networkComponents(networkComponents);

      // set operating system or blockDeviceTemplateGroup
      Optional<OperatingSystem> optionalOperatingSystem = tryExtractOperatingSystemFrom(imageId);
      if (optionalOperatingSystem.isPresent()) {
         virtualGuestBuilder.operatingSystem(optionalOperatingSystem.get());
      // the imageId specified is an id of a public/private/flex image
      } else {
         VirtualGuestBlockDeviceTemplateGroup blockDeviceTemplateGroup = VirtualGuestBlockDeviceTemplateGroup
                 .builder().globalIdentifier(imageId).build();
         virtualGuestBuilder.blockDeviceTemplateGroup(blockDeviceTemplateGroup).build();
      }
      // set multi-disks
      if (!templateOptions.getBlockDevices().isEmpty()) {
         List<VirtualGuestBlockDevice> blockDevices = getBlockDevices(templateOptions.getBlockDevices(), diskType);
         virtualGuestBuilder.blockDevices(blockDevices);
      }
      // set dedicatedAccountHostOnlyFlag
      if (templateOptions.isDedicatedAccountHostOnlyFlag() != null) {
         virtualGuestBuilder.dedicatedAccountHostOnly(templateOptions.isDedicatedAccountHostOnlyFlag());
      }
      // set privateNetworkOnlyFlag
      if (templateOptions.isPrivateNetworkOnlyFlag() != null) {
         virtualGuestBuilder.privateNetworkOnlyFlag(templateOptions.isPrivateNetworkOnlyFlag());
      }
      // set primaryNetworkComponent.networkVlan.id
      if (templateOptions.getPrimaryNetworkComponentNetworkVlanId() != null) {
         int primaryNetworkComponentNetworkVlanId = templateOptions.getPrimaryNetworkComponentNetworkVlanId();
         virtualGuestBuilder.primaryNetworkComponent(
                 VirtualGuestNetworkComponent.builder()
                         .networkVlan(NetworkVlan.builder().id(primaryNetworkComponentNetworkVlanId).build())
                         .build());
      }
      // set primaryBackendNetworkComponent.networkVlan.id
      if (templateOptions.getPrimaryBackendNetworkComponentNetworkVlanId() != null) {
         int primaryBackendNetworkComponentNetworkVlanId = templateOptions.getPrimaryBackendNetworkComponentNetworkVlanId();
         virtualGuestBuilder.primaryBackendNetworkComponent(
                 VirtualGuestNetworkComponent.builder()
                         .networkVlan(NetworkVlan.builder().id(primaryBackendNetworkComponentNetworkVlanId).build())
                         .build());
      }
      // set postInstallScriptUri
      if (templateOptions.getPostInstallScriptUri() != null) {
         // Specifies the uri location of the script to be downloaded and run after installation is complete.
         virtualGuestBuilder.postInstallScriptUri(templateOptions.getPostInstallScriptUri());
      }
      // set userData
      if (templateOptions.getUserData() != null) {
         virtualGuestBuilder.virtualGuestAttribute(VirtualGuestAttribute.builder().value(templateOptions.getUserData()).build());
      }
      // set sshKeys
      if (!templateOptions.getSshKeys().isEmpty()) {
         Set<SecuritySshKey> sshKeys = Sets.newHashSet();
         for (int sshKeyId : templateOptions.getSshKeys()) {
            sshKeys.add(SecuritySshKey.builder().id(sshKeyId).build());
         }
         virtualGuestBuilder.sshKeys(sshKeys);
      }

      VirtualGuest virtualGuest = virtualGuestBuilder.build();
      logger.debug(">> creating new VirtualGuest(%s)", virtualGuest);
      VirtualGuest result = api.getVirtualGuestApi().createVirtualGuest(virtualGuest);
      logger.trace("<< VirtualGuest(%s)", result.getId());

      // tags
      if (!templateOptions.getTags().isEmpty()) {
         api.getVirtualGuestApi().setTags(result.getId(), templateOptions.getTags());
      }

      // notes
      if (!Strings.isNullOrEmpty(notes)) {
         api.getVirtualGuestApi().setNotes(result.getId(), notes);
      }

      logger.debug(">> awaiting login details for virtualGuest(%s)", result.getId());
      boolean orderInSystem = loginDetailsTester.apply(result);
      logger.trace("<< VirtualGuest(%s) complete(%s)", result.getId(), orderInSystem);

      if (!orderInSystem) {
         logger.warn("VirtualGuest(%s) doesn't have login details within %sms so it will be destroyed.", result,
              Long.toString(guestLoginDelay));
         api.getVirtualGuestApi().deleteVirtualGuest(result.getId());
         throw new IllegalStateException(format("VirtualGuest(%s) is being destroyed as it doesn't have login details" +
                 " after %sms. Please, try by increasing `jclouds.softlayer.virtualguest.login_details_delay` and " +
                 " try again", result, Long.toString(guestLoginDelay)));
      }
      result = api.getVirtualGuestApi().getVirtualGuest(result.getId());
      Password pwd = get(result.getOperatingSystem().getPasswords(), 0);
      return new NodeAndInitialCredentials<VirtualGuest>(result, result.getId() + "",
              LoginCredentials.builder().user(pwd.getUsername()).password(pwd.getPassword()).build());
   }

   private String getNotes(SoftLayerTemplateOptions templateOptions) {
      String notes = null;
      Map<String, String> meta = templateOptions.getUserMetadata();
      if (meta != null) {
         notes = meta.get(USER_META_NOTES);
         if (!Strings.isNullOrEmpty(notes)) {
            checkArgument(notes.length() <= USER_META_NOTES_MAX_LENGTH, "'notes' property in user metadata should be long at most " + USER_META_NOTES_MAX_LENGTH + " characters.");
         }
      }
      return notes;
   }

   @Override
   public Iterable<Hardware> listHardwareProfiles() {
      ContainerVirtualGuestConfiguration virtualGuestConfiguration = createObjectOptionsSupplier.get();
      Builder<Hardware> hardware = ImmutableSortedSet.orderedBy(new Comparator<Hardware>() {
         @Override
         public int compare(Hardware h1, Hardware h2) {
            List<? extends Volume> volumes1 = h1.getVolumes();
            List<? extends Volume> volumes2 = h2.getVolumes();
            ComparisonChain comparisonChain = ComparisonChain.start().compare(getCores(h1), getCores(h2))
                    .compare(h1.getRam(), h2.getRam())
                    .compare(getSpace(h1), getSpace(h2))
                    .compare(getBootableDeviceType(h1), getBootableDeviceType(h2));
            if (!volumes1.isEmpty() && !volumes2.isEmpty() && volumes1.size() == volumes2.size()) {
               for (int i = 0; i < volumes1.size(); i++) {
                  comparisonChain = comparisonChain.compare(volumes1.get(i).getType(), volumes2.get(i).getType());
               }
            }
            return comparisonChain.result();
         }
      });
      for (VirtualGuestBlockDevice blockDevice : virtualGuestConfiguration.getVirtualGuestBlockDevices()) {
         float capacity = blockDevice.getVirtualDiskImage().getCapacity();
         Type type = blockDevice.getVirtualGuest().isLocalDiskFlag() ? Type.LOCAL : Type.SAN;
         if (blockDevice.getDevice().equals(BOOTABLE_DEVICE)) {
            for (Integer cpus : virtualGuestConfiguration.getCpusOfProcessors()) {
               for (Integer memory : virtualGuestConfiguration.getMemories()) {
                  String id = format("cpu=%s,memory=%s,disk=%s,type=%s", cpus, memory, round(capacity), type);
                  hardware.add(new HardwareBuilder()
                          .ids(id)
                          .ram(memory)
                          .processors(ImmutableList.of(new Processor(cpus, 2)))
                          .hypervisor("XenServer")
                          .volumes(ImmutableList.<Volume>of(
                                  new VolumeImpl(blockDevice.getId() + "",
                                          type,
                                          capacity,
                                          blockDevice.getDevice(),
                                          blockDevice.getBootableFlag() == 1,
                                          true)))
                          .build());
               }
            }
         }
      }
      return hardware.build();
   }

   @Override
   public Set<OperatingSystem> listImages() {
      Set<OperatingSystem> result = Sets.newHashSet();
      // add allObjects filtered by the available OS
      Set<SoftwareDescription> allObjects = api.getSoftwareDescriptionApi().getAllObjects();
      for (OperatingSystem os : createObjectOptionsSupplier.get().getVirtualGuestOperatingSystems()) {
         result.addAll(FluentIterable.from(allObjects)
                 .filter(new IsOperatingSystem())
                 .filter(new HasSameOsReferenceCode(os.getOperatingSystemReferenceCode()))
                 .transform(new SoftwareDescriptionToOperatingSystem(os.getId()))
                 .toSet());
      }
      return result;
   }

   @Override
   public OperatingSystem getImage(final String id) {
      // look for imageId among stock images
      Optional<OperatingSystem> operatingSystemOptional = tryFind(listImages(),
              new Predicate<OperatingSystem>() {
                 @Override
                 public boolean apply(OperatingSystem input) {
                    return input.getId().equals(id);
                 }
              }
      );
      if (operatingSystemOptional.isPresent()) return operatingSystemOptional.get();

      // if imageId is not a stock image, it searches among private and public images
      Stopwatch stopwatch = Stopwatch.createStarted();
      VirtualGuestBlockDeviceTemplateGroup image = api.getVirtualGuestBlockDeviceTemplateGroupApi().getObject(id);
      logger.trace("<< Image(%s) found in (%s)", id, stopwatch.elapsed(TimeUnit.SECONDS));
      return tryExtractOperatingSystemFrom(image).orNull();
   }

   @Override
   public Iterable<VirtualGuest> listNodes() {
      return api.getAccountApi().listVirtualGuests();
   }

   @Override
   public Iterable<VirtualGuest> listNodesByIds(final Iterable<String> ids) {
      return filter(listNodes(), new Predicate<VirtualGuest>() {

         @Override
         public boolean apply(VirtualGuest server) {
            return contains(ids, server.getId());
         }
      });
   }

   @Override
   public Iterable<Datacenter> listLocations() {
      Set<Datacenter> result = Sets.newHashSet();
      Set<Datacenter> unfiltered = api.getDatacenterApi().listDatacenters();
      Set<Datacenter> datacenterAvailable = createObjectOptionsSupplier.get().getVirtualGuestDatacenters();
      for (Datacenter datacenter : datacenterAvailable) {
         final String datacenterName = datacenter.getName();
         result.addAll(Sets.newHashSet(filter(unfiltered,
                 new Predicate<Datacenter>() {
                    @Override
                    public boolean apply(Datacenter input) {
                       return input.getName().equals(datacenterName);
                    }
                 })));
      }
      return result;
   }

   @Override
   public VirtualGuest getNode(String id) {
      long serverId = Long.parseLong(id);
      return api.getVirtualGuestApi().getVirtualGuest(serverId);
   }

   @Override
   public void destroyNode(String id) {
      VirtualGuest guest = getNode(id);
      if (guest == null) return;
      logger.debug(">> awaiting virtualGuest(%s) without active transactions", guest.getId());
      checkState(retry(new Predicate<VirtualGuest>() {
         public boolean apply(VirtualGuest guest) {
               return getNode(guest.getId() + "").getActiveTransactionCount() == 0;
         }
      }, activeTransactionsDelay).apply(guest), "%s still has active transactions!", guest);
      logger.debug(">> canceling virtualGuest with globalIdentifier(%s)", id);
      checkState(api.getVirtualGuestApi().deleteVirtualGuest(guest.getId()), "server(%s) still there after deleting!?", id);
   }

   @Override
   public void rebootNode(String id) {
      api.getVirtualGuestApi().rebootHardVirtualGuest(Long.parseLong(id));
   }

   @Override
   public void resumeNode(String id) {
      api.getVirtualGuestApi().resumeVirtualGuest(Long.parseLong(id));
   }

   @Override
   public void suspendNode(String id) {
      api.getVirtualGuestApi().pauseVirtualGuest(Long.parseLong(id));
   }

   /**
    * This method will deliberately skip device position 1 as it is reserved to SWAP
    * @param blockDeviceCapacities list of blockDevices to be attached
    * @param diskType disks can be LOCAL or SAN
    * @return
    */
   private static List<VirtualGuestBlockDevice> getBlockDevices(List<Integer> blockDeviceCapacities, String diskType) {
      ImmutableList.Builder<VirtualGuestBlockDevice> blockDevicesBuilder = ImmutableList.builder();
      int devicePosition = 0;
      for (int i = 0; i < blockDeviceCapacities.size(); i++) {
         if (i > 0) { devicePosition = i + 1; }
         blockDevicesBuilder.add(VirtualGuestBlockDevice.builder()
                 .device(devicePosition + "")
                 .diskImage(VirtualDiskImage.builder()
                         .capacity(blockDeviceCapacities.get(i))
                         .typeId(Type.valueOf(diskType).ordinal())
                         .build())
                 .build());
      }
      return blockDevicesBuilder.build();
   }

   private static boolean isLocalDisk(String diskType) {
      return diskType.equalsIgnoreCase(Type.LOCAL.name());
   }

   private static int getBootableDeviceType(Hardware hardware) {
      List<? extends Volume> volumes = hardware.getVolumes();
      Optional<? extends Volume> optionalBootableVolume = tryFind(volumes, new Predicate<Volume>() {
         @Override
         public boolean apply(Volume volume) {
            return volume.getDevice().equals(BOOTABLE_DEVICE);
         }
      });
      if (!optionalBootableVolume.isPresent()) {
         return Type.LOCAL.ordinal();
      }
      return optionalBootableVolume.get().getType().ordinal();
   }

   private Optional<OperatingSystem> tryExtractOperatingSystemFrom(final String imageId) {
      Set<OperatingSystem> operatingSystemsAvailable = createObjectOptionsSupplier.get().getVirtualGuestOperatingSystems();
      return FluentIterable.from(operatingSystemsAvailable)
              .filter(new Predicate<OperatingSystem>() {
                 @Override
                 public boolean apply(OperatingSystem input) {
                    if (input == null) return false;
                    return input.getId().contains(imageId);
                 }
              })
              .first();
   }

   private Optional<OperatingSystem> tryExtractOperatingSystemFrom(VirtualGuestBlockDeviceTemplateGroup image) {
      if (image.getGlobalIdentifier() == null) return Optional.absent();
      return FluentIterable.from(image.getChildren())
              .transformAndConcat(new BlockDeviceTemplateGroupToBlockDeviceTemplateIterable())
              .filter(new IsBootableDevice())
              .transformAndConcat(new BlockDeviceTemplateToDiskImageSoftware())
              .transform(new DiskImageSoftwareToSoftwareDescription())
              .filter(new IsOperatingSystem())
              .transform(new SoftwareDescriptionToOperatingSystem(image.getGlobalIdentifier()))
              .first();
   }

   public static class VirtualGuestHasLoginDetailsPresent implements Predicate<VirtualGuest> {
      private final SoftLayerApi client;

      @Inject
      public VirtualGuestHasLoginDetailsPresent(SoftLayerApi client) {
         this.client = checkNotNull(client, "client was null");
      }

      @Override
      public boolean apply(VirtualGuest guest) {
         checkNotNull(guest, "virtual guest was null");

         VirtualGuest virtualGuest = client.getVirtualGuestApi().getVirtualGuest(guest.getId());
         boolean hasBackendIp = virtualGuest.getPrimaryBackendIpAddress() != null;
         boolean hasPrimaryIp = virtualGuest.getPrimaryIpAddress() != null;
         boolean hasPasswords = virtualGuest.getOperatingSystem() != null
                 && !virtualGuest.getOperatingSystem().getPasswords().isEmpty();

         return virtualGuest.isPrivateNetworkOnly() ? hasBackendIp && hasPasswords : hasBackendIp && hasPrimaryIp && hasPasswords;
      }
   }

   private static class SoftwareDescriptionToOperatingSystem implements Function<SoftwareDescription, OperatingSystem> {
      private final String osId;

      public SoftwareDescriptionToOperatingSystem(String osId) {
         this.osId = osId;
      }

      @Override
      public OperatingSystem apply(SoftwareDescription input) {
         return OperatingSystem.builder().id(osId)
                                         .softwareLicense(SoftwareLicense.builder().softwareDescription(input).build())
                                         .operatingSystemReferenceCode(input.getReferenceCode())
                                         .build();
      }
   }

   private static class IsBootableDevice implements Predicate<VirtualGuestBlockDeviceTemplate> {
      @Override
      public boolean apply(VirtualGuestBlockDeviceTemplate blockDeviceTemplate) {
         return blockDeviceTemplate.getDevice().equals(BOOTABLE_DEVICE);
      }
   }

   private static class BlockDeviceTemplateGroupToBlockDeviceTemplateIterable implements Function<VirtualGuestBlockDeviceTemplateGroup,
                         Iterable<VirtualGuestBlockDeviceTemplate>> {
      @Override
      public Iterable<VirtualGuestBlockDeviceTemplate> apply(VirtualGuestBlockDeviceTemplateGroup input) {
         return input.getBlockDevices();
      }
   }

   private static class BlockDeviceTemplateToDiskImageSoftware implements Function<VirtualGuestBlockDeviceTemplate, Iterable<VirtualDiskImageSoftware>> {
      @Override
      public Iterable<VirtualDiskImageSoftware> apply(VirtualGuestBlockDeviceTemplate bootableDevice) {
         return bootableDevice.getDiskImage().getSoftwareReferences();
      }
   }

   private static class DiskImageSoftwareToSoftwareDescription implements Function<VirtualDiskImageSoftware, SoftwareDescription> {
      @Override
      public SoftwareDescription apply(VirtualDiskImageSoftware software) {
         return software.getSoftwareDescription();
      }
   }

   private static class HasSameOsReferenceCode implements Predicate<SoftwareDescription> {
      private final String osReferenceCode;

      public HasSameOsReferenceCode(String osReferenceCode) {
         this.osReferenceCode = osReferenceCode;
      }

      @Override
      public boolean apply(SoftwareDescription input) {
         return input.getReferenceCode().equals(osReferenceCode);
      }
   }

   private static class IsOperatingSystem implements Predicate<SoftwareDescription> {
      @Override
      public boolean apply(SoftwareDescription softwareDescription) {
         // operatingSystem is set to '1' if this Software Description describes an Operating System.
         return softwareDescription.getOperatingSystem() == 1;
      }
   }
}
