package com.tofly.toflygateway.swagger;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.*;


@Component
@Slf4j
public class ToflyRouteManager implements ApplicationEventPublisherAware {

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private RouteLocator routeLocator;

    private List<RouteDefinition> list = new ArrayList<>();

    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    public void setRoute() {
        List<String> services = discoveryClient.getServices();
        Set<String> routes = new HashSet<>();
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        ;
        services.stream().filter(s -> (!routes.contains(s) && !s.equalsIgnoreCase("tofly-config")
                && !s.equalsIgnoreCase("tofly-eureka") && !s.equalsIgnoreCase("tofly-getway"))).forEach(
                serverId -> {
                    RouteDefinition definition = new RouteDefinition();
//                    definition.setId(PRE_SERVER+serverId);
                    definition.setId(serverId);
                    URI uri = URI.create("lb://" + serverId);
                    definition.setUri(uri);
                    PredicateDefinition predicate = new PredicateDefinition();
                    predicate.setName("Path");
                    Map<String, String> predicateParams = new HashMap<>(8);
                    predicateParams.put(NameUtils.GENERATED_NAME_PREFIX + "0", "/" + serverId + "/**");
                    predicate.setArgs(predicateParams);
                    definition.setPredicates(Arrays.asList(predicate));
                    log.info(".........添加应用：{},", serverId);
                    list.add(definition);
                    routeDefinitionWriter.save(Mono.just(definition)).subscribe();
                    notifyChanged();
                }
        );
    }

    private void notifyChanged() {
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    public List<RouteDefinition> getRouteDefinitions() {
        return list;
    }

}
