/*
 * Copyright 2013-2015 the original author or authors.
 *
 * Licensed 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.springframework.cloud.consul.discovery.filters;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.cloud.consul.discovery.ConsulServer;

import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.QueryParams;
import com.ecwid.consul.v1.health.model.Check;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerListFilter;

/**
 * Created by nicu on 12.03.2015.
 */
public class ServiceCheckServerListFilter implements ServerListFilter<Server> {

	private ConsulClient client;

	public ServiceCheckServerListFilter(ConsulClient client) {
		this.client = client;
	}

	@Override
	public List<Server> getFilteredListOfServers(List<Server> servers) {
		Set<String> passingServiceIds = getPassingServiceIds(servers);
		List<Server> okServers = new ArrayList<>(servers.size());
		for (Server server : servers) {
			String serviceId = server.getMetaInfo().getInstanceId();
			if (passingServiceIds.contains(serviceId)) {
				ConsulServer consulServer = ConsulServer.class.cast(server);
				List<Check> nodeChecks = client.getHealthChecksForNode(
						consulServer.getNode(), QueryParams.DEFAULT).getValue();
				boolean passingNodeChecks = true;
				for (Check check : nodeChecks) {
					if (check.getStatus() != Check.CheckStatus.PASSING) {
						passingNodeChecks = false;
						break;
					}
				}
				if (passingNodeChecks) {
					okServers.add(server);
				}
			}
		}
		return okServers;
	}

	private Set<String> getPassingServiceIds(List<Server> servers) {
		Set<String> serviceIds = new HashSet<>(1);
		for (Server server : servers) {
			serviceIds.add(server.getMetaInfo().getInstanceId());
		}
		for (String serviceId : serviceIds) {
			List<Check> serviceChecks = client.getHealthChecksForService(serviceId,
					QueryParams.DEFAULT).getValue();
			for (Check check : serviceChecks) {
				if (check.getStatus() != Check.CheckStatus.PASSING) {
					serviceIds.remove(check.getServiceId());
				}
			}
		}
		return serviceIds;
	}

}

@@ -725,125 +725,12 @@
 til.
-HashSet;%0Aimport java.util.List;%0Aimport java.util.Set;%0A%0Aimport org.springframework.cloud.consul.discovery.ConsulServer
+List
 ;%0A%0Ai
@@ -1274,73 +1274,8 @@
 ) %7B%0A
-%09%09Set%3CString%3E passingServiceIds = getPassingServiceIds(servers);%0A
 %09%09Li
@@ -1330,16 +1330,17 @@
 ize());%0A
+%0A
 %09%09for (S
@@ -1375,25 +1375,23 @@
 %09String 
-serviceId
+appName
  = serve
@@ -1413,792 +1413,131 @@
 .get
-InstanceId();%0A%09%09%09if (passingServiceIds.contains(serviceId)) %7B%0A%09%09%09%09ConsulServer consulServer = ConsulServer.class.cast(server);%0A%09%09%09%09List%3CCheck%3E nodeChecks = client.getHealthChecksForNode(%0A%09%09%09%09%09%09consulServer.getNode(), QueryParams.DEFAULT).getValue();%0A%09%09%09%09boolean passingNodeChecks = true;%0A%09%09%09%09for (Check check : nodeChecks) %7B%0A%09%09%09%09%09if (check.getStatus() != Check.CheckStatus.PASSING) %7B%0A%09%09%09%09%09%09passingNodeChecks = false;%0A%09%09%09%09%09%09break;%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D%0A%09%09%09%09if (passingNodeChecks) %7B%0A%09%09%09%09%09okServers.add(server);%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return okServers;%0A%09%7D%0A%0A%09private Set%3CString%3E getPassingServiceIds(List%3CServer%3E servers) %7B%0A%09%09Set%3CString%3E serviceIds = new HashSet%3C%3E(1);%0A%09%09for (Server server : servers) %7B%0A%09%09%09serviceIds.add(server.getMetaInfo().getInstanceId());%0A%09%09%7D%0A%09%09for (String serviceId : serviceIds) %7B
+AppName();%0A%09%09%09String instanceId = server.getMetaInfo().getInstanceId();%0A%09%09%09//TODO: cache getHealthChecks? this is hit often
 %0A%09%09%09
@@ -1597,25 +1597,23 @@
 Service(
-serviceId
+appName
 ,%0A%09%09%09%09%09Q
@@ -1644,16 +1644,45 @@
 alue();%0A
+%09%09%09boolean serviceOk = true;%0A
 %09%09%09for (
@@ -1720,16 +1720,65 @@
 %09%09%09%09if (
+check.getServiceId().equals(instanceId)%0A%09%09%09%09%09%09&& 
 check.ge
@@ -1835,47 +1835,114 @@
 vice
-Ids.remove(check.getServiceId());%0A%09%09%09%09%7D
+Ok = false;%0A%09%09%09%09%09break; // just need one to fail%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%09if (serviceOk) %7B%0A%09%09%09%09okServers.add(server);
 %0A%09%09%09
@@ -1947,16 +1947,17 @@
 %09%09%7D%0A%09%09%7D%0A
+%0A
 %09%09return
@@ -1961,17 +1961,16 @@
 urn 
-serviceId
+okServer
 s;%0A%09

update to only verify check of service, not node