package com.brighttag.agathon.service.impl;

import java.util.Collection;

import javax.annotation.Nullable;

import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.SetMultimap;
import com.google.inject.Inject;
import com.google.inject.name.Named;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.brighttag.agathon.model.CassandraInstance;
import com.brighttag.agathon.model.CassandraRing;
import com.brighttag.agathon.service.SeedService;

/**
 * A {@link SeedService} that includes a specified number of seeds per data center.
 *
 * @author codyaray
 * @since 5/25/12
 */
public class PerDataCenterSeedService implements SeedService {

  private static final Logger LOG = LoggerFactory.getLogger(PerDataCenterSeedService.class);

  private static final Function<CassandraInstance, String> INSTANCE_TO_SEED =
    new Function<CassandraInstance, String>() {
      @Override
      public @Nullable String apply(@Nullable CassandraInstance instance) {
        return (instance != null) ?
            Objects.firstNonNull(instance.getFullyQualifiedDomainName(), instance.getPublicIpAddress()) : null;
      }
    };

  private final int numSeeds;

  @Inject
  public PerDataCenterSeedService(@Named(ServiceModule.SEEDS_PER_DATACENTER_PROPERTY) int numSeeds) {
    this.numSeeds = numSeeds;
  }

  @Override
  public ImmutableSet<String> getSeeds(CassandraRing ring) {
    ImmutableSet.Builder<String> seedBuilder = ImmutableSet.builder();
    SetMultimap<String, CassandraInstance> dataCenterToInstanceMap =
        buildDataCenterToInstanceMap(ring.getInstances());

    for (String dc : dataCenterToInstanceMap.keySet()) {
      seedBuilder.addAll(getSeeds(dc, dataCenterToInstanceMap.get(dc)));
    }

    return seedBuilder.build();
  }

  /**
   * Return the first {@code numSeeds} seeds from the {@code instancesInDC} collection
   * for the given {@code dataCenter}.
   *
   * @param dataCenter the data center name
   * @param instancesInDC a collection of instances in the data center
   * @return the public DNS names or IP addresses of the first {@code numSeeds} hosts
   */
  private Iterable<String> getSeeds(String dataCenter, Collection<CassandraInstance> instancesInDC) {
    int size = instancesInDC.size();
    if (size < numSeeds) {
      LOG.warn("Too few seeds for data center '{}'. Continuing with {} seeds.", dataCenter, size);
    }

    return Iterables.transform(Iterables.limit(instancesInDC, numSeeds), INSTANCE_TO_SEED);
  }

  private static SetMultimap<String, CassandraInstance> buildDataCenterToInstanceMap(
      ImmutableSet<CassandraInstance> instances) {
    ImmutableSetMultimap.Builder<String, CassandraInstance> dataCenterToInstanceMap =
        ImmutableSetMultimap.builder();
    for (CassandraInstance instance : instances) {
      dataCenterToInstanceMap.put(instance.getDataCenter(), instance);
    }
    return dataCenterToInstanceMap.build();
  }

}

@@ -42,73 +42,8 @@
 l;%0A%0A
-import java.util.Collection;%0A%0Aimport javax.annotation.Nullable;%0A%0A
 impo
@@ -78,16 +78,16 @@
 nction;%0A
+
 import c
@@ -267,54 +267,8 @@
 es;%0A
-import com.google.common.collect.SetMultimap;%0A
 impo
@@ -993,26 +993,16 @@
  public 
-@Nullable 
 String a
@@ -1010,18 +1010,8 @@
 ply(
-@Nullable 
 Cass
@@ -1055,41 +1055,8 @@
 urn 
-(instance != null) ?%0A            
 Obje
@@ -1146,15 +1146,8 @@
 s())
- : null
 ;%0A  
@@ -1486,16 +1486,25 @@
 ();%0A    
+Immutable
 SetMulti
@@ -2197,18 +2197,20 @@
 er, 
-Collection
+ImmutableSet
 %3CCas
@@ -2509,16 +2509,16 @@
 );%0A  %7D%0A%0A
-
   privat
@@ -2526,16 +2526,25 @@
  static 
+Immutable
 SetMulti

Fix checkstyle warning and remove unnecessary null checks (using immutable collections)