package lt.nkts.cassandra;

import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.Response;
import com.ecwid.consul.v1.catalog.model.CatalogService;
import com.ecwid.consul.v1.kv.model.GetValue;
import com.google.common.base.Splitter;
import org.apache.cassandra.locator.SeedProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.*;

public class ConsulSeedProvider implements SeedProvider {

    private static final Logger logger = LoggerFactory.getLogger(ConsulSeedProvider.class);

    private ConsulClient client;

    private URL consul_url;
    private Boolean consul_use_kv;
    private String consul_kv_prefix;
    private String consul_service_name;
    private Collection<String> consul_service_tags;

    public ConsulSeedProvider(Map<String, String> args) {
        try {
            consul_url = new URL(System.getProperty("consul.url", "http://localhost:8500/"));
            consul_use_kv = BooleanUtils.toBoolean(System.getProperty("consul.kv.enabled", "false"), "true", "false");
            consul_kv_prefix = System.getProperty("consul.kv.prefix", "cassandra/seeds");
            consul_service_name = System.getProperty("consul.service.name", "cassandra");
            consul_service_tags = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(System.getProperty("consul.service.tags", ""));
        } catch (Exception e) {
            logger.error(e.toString());
        }

        logger.debug("consul_url {}", consul_url);
        logger.debug("consul_service_name {}", consul_service_name);
        logger.debug("consul_service_tags {}", consul_service_tags.toString());
        logger.debug("consul_service_tags size [{}]", consul_service_tags.size());
        logger.debug("consul_use_kv {}", consul_use_kv);
        logger.debug("consul_kv_prefix {}", consul_kv_prefix);
    }

    public List<InetAddress> getSeeds() {
        client = new ConsulClient(String.format("%s:%s", consul_url.getHost(), consul_url.getPort()));

        List<InetAddress> seeds = new ArrayList<InetAddress>();

        if (consul_use_kv) {
            Response response = client.getKVValues(consul_kv_prefix);
            List all = (ArrayList<GetValue>) response.getValue();
            if (all == null) {
                return Collections.EMPTY_LIST;
            }

            for (Object gv : all) {
                logger.info("kv: {}", gv);

                GetValue record = (GetValue) gv;
                String[] parts = record.getKey().split("/");
                String host = parts[parts.length - 1];

                try {
                    seeds.add(InetAddress.getByName(host));
                } catch (UnknownHostException ex) {
                    logger.warn("Seed provider couldn't lookup host {}", host);
                }
            }

        } else {
            Response<List<CatalogService>> response = client.getCatalogService(consul_service_name, null);

            for (CatalogService svc : response.getValue()) {
                try {
                    logger.debug("Service [{}]", svc.toString());

                    if (CollectionUtils.isNotEmpty(consul_service_tags)) {
                        List<String> stags = svc.getServiceTags();

                        logger.debug("Service tagged with {}", stags.toString());
                        logger.debug("I'm looking for {}", consul_service_tags.toString());

                        if (CollectionUtils.containsAll(stags, consul_service_tags)) {
                            seeds.add(InetAddress.getByName(svc.getServiceAddress()));
                        }
                    } else {
                        seeds.add(InetAddress.getByName(svc.getServiceAddress()));
                    }

                } catch (Exception e) {
                    logger.warn("Adding seed {}", e.getMessage());
                }
            }
        }

        if (seeds.size() > 0) {
            logger.info("Seeds {}", seeds.toString());
        }

        return Collections.unmodifiableList(seeds);
    }
}

@@ -938,16 +938,61 @@
 ce_tags;
+%0A    private List%3CInetAddress%3E default_seeds;
 %0A%0A    pu
@@ -1039,24 +1039,580 @@
 ng%3E args) %7B%0A
+        // These are used as a fallback if we get nothing from Consul%0A        default_seeds = new ArrayList%3CInetAddress%3E();%0A        String seeds = args.get(%22seeds%22);%0A        if (seeds != null) %7B%0A            for (String host : Splitter.on(%22,%22).trimResults().omitEmptyStrings().split(seeds)) %7B%0A                try %7B%0A                    default_seeds.add(InetAddress.getByName(host));%0A                %7D catch (UnknownHostException ex) %7B%0A                    logger.warn(%22Seed provider couldn't lookup host %22 + host);%0A                %7D%0A            %7D%0A        %7D%0A%0A
         try 
@@ -2632,24 +2632,81 @@
 kv_prefix);%0A
+        logger.debug(%22default_seeds %7B%7D%22, default_seeds);%0A
     %7D%0A%0A    p
@@ -3146,18 +3146,39 @@
 ons.
-EMPTY_LIST
+unmodifiableList(default_seeds)
 ;%0A  
@@ -4752,33 +4752,32 @@
     %7D%0A        %7D%0A
-%0A
         if (seed
@@ -4782,26 +4782,135 @@
 eds.
-size() %3E 0) %7B%0A
+isEmpty()) %7B%0A            // We got nothing from Consul so add default seeds%0A            seeds.addAll(default_seeds);%0A   
     
+ %7D%0A
     
@@ -4952,35 +4952,24 @@
 oString());%0A
-        %7D%0A%0A
         retu

Return default seeds provided in config if Consul does not return any seeds