/*
 * 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.net.domain;

import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.util.Strings2.isCidrFormat;

import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;

import org.jclouds.net.util.IpPermissions;

import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

/**
 * Ingress access to a destination protocol on particular ports by source, which could be an ip
 * range (cidrblock), set of explicit security group ids in the current tenant, or security group
 * names in another tenant.
 *
 * @see IpPermissions
 */
@Beta
public class IpPermission implements Comparable<IpPermission> {
   public static Builder builder() {
      return new Builder();
   }

   public static class Builder {
      private IpProtocol ipProtocol;
      private int fromPort;
      private int toPort;
      private Multimap<String, String> tenantIdGroupNamePairs = LinkedHashMultimap.create();
      private Set<String> groupIds = Sets.newLinkedHashSet();
      private Set<String> cidrBlocks = Sets.newLinkedHashSet();
      private Set<String> exclusionCidrBlocks = Sets.newLinkedHashSet();

      /**
       * Creates a builder initialized from an existing permission.
       * @param permission The existing permission.
       * @return the builder.
       */
      public Builder fromPermission(IpPermission permission) {
         this.ipProtocol = permission.ipProtocol;
         this.fromPort = permission.fromPort;
         this.toPort = permission.toPort;
         this.tenantIdGroupNamePairs = LinkedHashMultimap.create();
         tenantIdGroupNamePairs.putAll(permission.tenantIdGroupNamePairs);
         this.groupIds = Sets.newLinkedHashSet();
         this.groupIds.addAll(permission.groupIds);
         this.cidrBlocks = Sets.newLinkedHashSet();
         this.cidrBlocks.addAll(permission.cidrBlocks);
         this.exclusionCidrBlocks = Sets.newLinkedHashSet();
         this.exclusionCidrBlocks.addAll(permission.exclusionCidrBlocks);
         return this;
      }

      /**
       * @see IpPermission#getIpProtocol()
       */
      public Builder ipProtocol(IpProtocol ipProtocol) {
         this.ipProtocol = ipProtocol;
         return this;
      }

      /**
       * @see IpPermission#getFromPort()
       */
      public Builder fromPort(int fromPort) {
         this.fromPort = fromPort;
         return this;
      }

      /**
       * @see IpPermission#getToPort()
       */
      public Builder toPort(int toPort) {
         this.toPort = toPort;
         return this;
      }

      /**
       * @see IpPermission#getTenantIdGroupNamePairs()
       */
      public Builder tenantIdGroupNamePair(String tenantId, String groupName) {
         this.tenantIdGroupNamePairs.put(tenantId, groupName);
         return this;
      }

      /**
       * @see IpPermission#getTenantIdGroupNamePairs()
       */
      public Builder tenantIdGroupNamePairs(Multimap<String, String> tenantIdGroupNamePairs) {
         this.tenantIdGroupNamePairs.putAll(tenantIdGroupNamePairs);
         return this;
      }

      /**
       * @see IpPermission#getCidrBlocks()
       */
      public Builder cidrBlock(String cidrBlock) {
         checkArgument(isCidrFormat(cidrBlock), "cidrBlock %s is not a valid CIDR", cidrBlock);
         this.cidrBlocks.add(cidrBlock);
         return this;
      }

      /**
       * @see IpPermission#getCidrBlocks()
       */
      public Builder cidrBlocks(Iterable<String> cidrBlocks) {
         Iterables.addAll(this.cidrBlocks, transform(cidrBlocks, new Function<String, String>() {
            @Override
            public String apply(String input) {
               checkArgument(isCidrFormat(input), "input %s is not a valid CIDR", input);
               return input;
            }
         }));
         return this;
      }

      /**
       * @see IpPermission#getExclusionCidrBlocks()
       */
      @Beta
      public Builder exclusionCidrBlock(String exclusionCidrBlock) {
         checkArgument(isCidrFormat(exclusionCidrBlock), "exclusionCidrBlock %s is not a valid CIDR",
            exclusionCidrBlock);
         this.exclusionCidrBlocks.add(exclusionCidrBlock);
         return this;
      }

      /**
       * @see IpPermission#getExclusionCidrBlocks()
       */
      @Beta
      public Builder exclusionCidrBlocks(Iterable<String> exclusionCidrBlocks) {
         Iterables.addAll(this.exclusionCidrBlocks, transform(exclusionCidrBlocks, new Function<String, String>() {
            @Override
            public String apply(String input) {
               checkArgument(isCidrFormat(input), "input %s is not a valid CIDR", input);
               return input;
            }
         }));
         return this;
      }

      /**
       * @see IpPermission#getGroupIds()
       */
      public Builder groupId(String groupId) {
         this.groupIds.add(groupId);
         return this;
      }

      /**
       * @see IpPermission#getGroupIds()
       */
      public Builder groupIds(Iterable<String> groupIds) {
         Iterables.addAll(this.groupIds, groupIds);
         return this;
      }

      public IpPermission build() {
         return new IpPermission(ipProtocol, fromPort, toPort, tenantIdGroupNamePairs, groupIds, cidrBlocks,
            exclusionCidrBlocks);
      }
   }

   private final int fromPort;
   private final int toPort;
   private final Multimap<String, String> tenantIdGroupNamePairs;
   private final Set<String> groupIds;
   private final IpProtocol ipProtocol;
   private final Set<String> cidrBlocks;
   private final Set<String> exclusionCidrBlocks;

   public IpPermission(IpProtocol ipProtocol, int fromPort, int toPort,
                       Multimap<String, String> tenantIdGroupNamePairs, Iterable<String> groupIds, Iterable<String> cidrBlocks,
                       Iterable<String> exclusionCidrBlocks) {
      this.fromPort = fromPort;
      this.toPort = toPort;
      this.tenantIdGroupNamePairs = ImmutableMultimap.copyOf(checkNotNull(tenantIdGroupNamePairs,
         "tenantIdGroupNamePairs"));
      this.ipProtocol = checkNotNull(ipProtocol, "ipProtocol");
      this.groupIds = ImmutableSet.copyOf(checkNotNull(groupIds, "groupIds"));
      this.cidrBlocks = ImmutableSet.copyOf(checkNotNull(cidrBlocks, "cidrBlocks"));
      this.exclusionCidrBlocks = ImmutableSet.copyOf(checkNotNull(exclusionCidrBlocks, "exclusionCidrBlocks"));
   }


   /**
    * destination IP protocol
    */
   public IpProtocol getIpProtocol() {
      return ipProtocol;
   }

   /**
    * Start of destination port range for the TCP and UDP protocols, or an ICMP type number. An ICMP
    * type number of -1 indicates a wildcard (i.e., any ICMP type number).
    */
   public int getFromPort() {
      return fromPort;
   }

   /**
    * End of destination port range for the TCP and UDP protocols, or an ICMP code. An ICMP code of
    * -1 indicates a wildcard (i.e., any ICMP code).
    */
   public int getToPort() {
      return toPort;
   }

   /**
    * source of traffic allowed is on basis of another group in a tenant, as opposed to by cidr
    */
   public Multimap<String, String> getTenantIdGroupNamePairs() {
      return tenantIdGroupNamePairs;
   }

   /**
    * source of traffic allowed is on basis of another groupid in the same tenant
    */
   public Set<String> getGroupIds() {
      return groupIds;
   }

   /**
    * source of traffic is a cidrRange
    */
   public Set<String> getCidrBlocks() {
      return cidrBlocks;
   }

   /**
    * Traffic whose source matches any of these CIDR blocks will be blocked
    */
   @Beta
   public Set<String> getExclusionCidrBlocks() {
      return exclusionCidrBlocks;
   }


   /**
    * {@inheritDoc}
    */
   @Override
   public int compareTo(IpPermission that) {
      if (this == that) return 0;
      final int proto = getIpProtocol().compareTo(that.getIpProtocol());
      if (proto != 0) return proto;

      final int fromP = Integer.valueOf(this.fromPort).compareTo(Integer.valueOf(that.fromPort));
      if (fromP != 0) return fromP;

      final int toP = Integer.valueOf(this.toPort).compareTo(Integer.valueOf(that.toPort));
      if (toP != 0) return toP;

      final int tenantGroups = new LinkedMultiMapComparator<String, String>()
         .compare(this.tenantIdGroupNamePairs, that.tenantIdGroupNamePairs);
      if (tenantGroups != 0) return tenantGroups;

      final int groupIdComp = new CollectionComparator<String>()
         .compare(this.groupIds, that.groupIds);
      if (groupIdComp != 0) return groupIdComp;

      final int cidrComp = new CollectionComparator<String>()
         .compare(this.cidrBlocks, that.cidrBlocks);
      if (cidrComp != 0) return cidrComp;

      final int exclusionsComp = new CollectionComparator<String>()
         .compare(this.exclusionCidrBlocks, that.exclusionCidrBlocks);
      if (exclusionsComp != 0) return exclusionsComp;

      return 0;
   }

   @Override
   public boolean equals(Object o) {
      if (this == o)
         return true;
      // allow subtypes
      if (o == null || !(o instanceof IpPermission))
         return false;
      IpPermission that = IpPermission.class.cast(o);
      return equal(this.ipProtocol, that.ipProtocol) && equal(this.fromPort, that.fromPort)
         && equal(this.toPort, that.toPort) && equal(this.tenantIdGroupNamePairs, that.tenantIdGroupNamePairs)
         && equal(this.groupIds, that.groupIds) && equal(this.cidrBlocks, that.cidrBlocks)
         && equal(this.exclusionCidrBlocks, that.exclusionCidrBlocks);
   }

   @Override
   public int hashCode() {
      return Objects.hashCode(ipProtocol, fromPort, toPort, tenantIdGroupNamePairs, groupIds, cidrBlocks,
         exclusionCidrBlocks);
   }

   @Override
   public String toString() {
      return string().toString();
   }

   protected ToStringHelper string() {
      return Objects.toStringHelper("").add("ipProtocol", ipProtocol).add("fromPort", fromPort)
         .add("toPort", toPort).add("tenantIdGroupNamePairs", tenantIdGroupNamePairs).add("groupIds", groupIds)
         .add("cidrBlocks", cidrBlocks).add("exclusionCidrBlocks", exclusionCidrBlocks);
   }


   // A private tool for use in implementing a consistent compareTo relation.
   private static class LinkedMultiMapComparator<K extends Comparable, V> implements Comparator<Multimap<K, V>> {

      /**
       * Compares {@link Multimap}s, in order of iterators.
       * If two keys do not compare as zero, the key comparison result is used as the comparison result.
       * For keys that are equal, the value collections are compared with {@link CollectionComparator}.
       * If all entries compare as zero the map sizes determine the result.
       *
       * @param map1 The first map for comparison
       * @param map2 The second map for comparison
       * @return the comparison relation value
       */
      @Override
      public int compare(Multimap<K, V> map1, Multimap<K, V> map2) {
         final Iterator<K> leftIter = map1.keySet().iterator();
         final Iterator<K> rightIter = map2.keySet().iterator();
         while (leftIter.hasNext() && rightIter.hasNext()) {
            K key1 = leftIter.next();
            K key2 = rightIter.next();

            int keyComp = key1.compareTo(key2);
            if (keyComp != 0) return keyComp;

            final int valuesComp = new CollectionComparator().compare(map1.get(key1), map2.get(key2));
            if (valuesComp != 0) return valuesComp;
         }
         if (!leftIter.hasNext() && rightIter.hasNext()) {
            return -1;
         }
         if (leftIter.hasNext() && !rightIter.hasNext()) {
            return +1;
         }
         return 0;
      }
   }

   // A private tool for use in implementing a consistent compareTo relation.
   private static class CollectionComparator<T extends Comparable> implements Comparator<Collection<T>> {

      /**
       * Compares collections of comparable objects, in order of iterator.
       * Iterates through the collections in step.
       * If two entries do not compare as zero, the comparison result is the result of this method.
       * If all entries compare as zero, then the collection sizes determine the result.
       *
       * @param o1 The first collection to compare.
       * @param o2 The second collection to compare.
       * @return The comparison relation value.
       */
      @Override
      public int compare(Collection<T> o1, Collection<T> o2) {

         final Iterator<T> leftIter = o1.iterator();
         final Iterator<T> rightIter = o2.iterator();
         while (leftIter.hasNext() && rightIter.hasNext()) {
            int comp = leftIter.next().compareTo(rightIter.next());
            if (comp != 0) return comp;
         }
         if (!leftIter.hasNext() && rightIter.hasNext()) {
            return -1;
         }
         if (leftIter.hasNext() && !rightIter.hasNext()) {
            return +1;
         }
         return 0;
      }
   }

}
