/*
 * 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.openstack.nova.v2_0.compute.functions;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Predicates.or;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
import static org.jclouds.compute.util.ComputeServiceUtils.groupFromMapOrName;
import static org.jclouds.openstack.nova.v2_0.domain.Address.createV4;
import static org.jclouds.openstack.nova.v2_0.domain.Address.createV6;

import java.net.Inet4Address;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

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

import com.google.common.base.Optional;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v2_0.domain.Address;
import org.jclouds.openstack.nova.v2_0.domain.Server;
import org.jclouds.openstack.nova.v2_0.domain.Server.Status;
import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
import org.jclouds.openstack.nova.v2_0.domain.regionscoped.ServerInRegion;
import org.jclouds.openstack.v2_0.domain.Link;
import org.jclouds.util.InetAddresses2;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.net.InetAddresses;

/**
 * A function for transforming a nova-specific Server into a generic
 * NodeMetadata object.
 */
public class ServerInRegionToNodeMetadata implements Function<ServerInRegion, NodeMetadata> {
   @Resource
   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
   protected Logger logger = Logger.NULL;

   protected Map<Status, org.jclouds.compute.domain.NodeMetadata.Status> toPortableNodeStatus;
   protected final Supplier<Map<String, Location>> locationIndex;
   protected final Supplier<Set<? extends Image>> images;
   protected final Supplier<Set<? extends Hardware>> hardwares;
   protected final GroupNamingConvention nodeNamingConvention;

   @Inject
   public ServerInRegionToNodeMetadata(Map<Server.Status, NodeMetadata.Status> toPortableNodeStatus,
            Supplier<Map<String, Location>> locationIndex, @Memoized Supplier<Set<? extends Image>> images,
            @Memoized Supplier<Set<? extends Hardware>> hardwares, GroupNamingConvention.Factory namingConvention) {
      this.toPortableNodeStatus = checkNotNull(toPortableNodeStatus, "toPortableNodeStatus");
      this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix();
      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
      this.images = checkNotNull(images, "images");
      this.hardwares = checkNotNull(hardwares, "hardwares");
   }

   @Override
   public NodeMetadata apply(ServerInRegion serverInRegion) {
      Location region = locationIndex.get().get(serverInRegion.getRegion());
      checkState(region != null, "location %s not in locationIndex: %s", serverInRegion.getRegion(), locationIndex.get());
      Server from = serverInRegion.getServer();

      NodeMetadataBuilder builder = new NodeMetadataBuilder();
      builder.id(serverInRegion.slashEncode());
      builder.providerId(from.getId());
      builder.name(from.getName());
      builder.hostname(from.getName());
      builder.location(from.getHostId() != null ? new LocationBuilder().scope(LocationScope.HOST).id(from.getHostId())
            .description(from.getHostId()).parent(region).build() : region);
      builder.group(groupFromMapOrName(from.getMetadata(), from.getName(), nodeNamingConvention));
      addMetadataAndParseTagsFromCommaDelimitedValue(builder, from.getMetadata());

      if (from.getImage() != null) {
         builder.imageId(RegionAndId.fromRegionAndId(serverInRegion.getRegion(), from.getImage().getId()).slashEncode());
      }

      builder.operatingSystem(findOperatingSystemForServerOrNull(serverInRegion));
      builder.hardware(findHardwareForServerOrNull(serverInRegion));
      builder.status(toPortableNodeStatus.get(from.getStatus()));

      Set<Address> addresses = newHashSet(from.getAddresses().values());
      if (from.getAccessIPv4() != null) {
         addresses.add(createV4(from.getAccessIPv4()));
      }
      if (from.getAccessIPv6() != null) {
         addresses.add(createV6(from.getAccessIPv6()));
      }

      builder.publicAddresses(
            filter(
                  transform(
                        filter(addresses, or(isFloatingAddress, not(isPrivateAddress))),
                        AddressToStringTransformationFunction.INSTANCE),
                  isInet4Address));

      builder.privateAddresses(
            filter(
                  transform(
                        filter(addresses, and(not(isFloatingAddress), isPrivateAddress)),
                        AddressToStringTransformationFunction.INSTANCE),
                  isInet4Address));

      for (Link link : from.getLinks()) {
         if (link.getRelation().equals(Link.Relation.SELF)) {
            builder.uri(link.getHref());
         }
      }

      return builder.build();
   }

   public static final Predicate<Address> isFloatingAddress = new Predicate<Address>() {
      public boolean apply(Address in) {
         final Optional<String> addrType = in.getType();
         return addrType.isPresent() && "floating".equals(addrType.get());
      }
   };

   public static final Predicate<Address> isPrivateAddress = new Predicate<Address>() {
      public boolean apply(Address in) {
         return InetAddresses2.IsPrivateIPAddress.INSTANCE.apply(in.getAddr());
      }
   };

   public static final Predicate<String> isInet4Address = new Predicate<String>() {
      @Override
      public boolean apply(String input) {
         try {
            // Note we can do this, as InetAddress is now on the white list
            return InetAddresses.forString(input) instanceof Inet4Address;
         } catch (IllegalArgumentException e) {
            // could be a hostname
            return true;
         }
      }

   };

   public enum AddressToStringTransformationFunction implements Function<Address, String> {
      INSTANCE;
      @Override
      public String apply(Address address) {
         return address.getAddr();
      }
   }

   protected Hardware findHardwareForServerOrNull(ServerInRegion serverInRegion) {
      return findObjectOfTypeForServerOrNull(hardwares.get(), "hardware", serverInRegion.getServer().getFlavor().getId(),
            serverInRegion);
   }

   protected OperatingSystem findOperatingSystemForServerOrNull(ServerInRegion serverInRegion) {
      if (serverInRegion.getServer().getImage() != null) {
         Image image = findObjectOfTypeForServerOrNull(
               images.get(), "image", serverInRegion.getServer().getImage().getId(), serverInRegion);

         return (image != null) ? image.getOperatingSystem() : null;
      } else {
         return null;
      }

   }

   public <T extends ComputeMetadata> T findObjectOfTypeForServerOrNull(Set<? extends T> supply, String type,
         final String objectId, final RegionAndId serverInRegion) {
      try {
         return find(supply, new Predicate<T>() {
            @Override
            public boolean apply(T input) {
               return input.getId().equals(RegionAndId.fromRegionAndId(serverInRegion.getRegion(), objectId).slashEncode());
            }
         });
      } catch (NoSuchElementException e) {
         logger.trace("could not find %s with id(%s) for server(%s)", type, objectId, serverInRegion);
      }
      return null;
   }

}
