/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved. <a>http://www.crunii.com</a>
 */
package com.crunii.micro.config;

import com.crunii.micro.common.dto.Result;
import com.crunii.micro.common.dto.ServiceInst;
import com.crunii.micro.common.utils.DateUtil;
import com.crunii.micro.common.utils.StopUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author 田平 create 2020年4月13日下午5:26:13
 */
@Slf4j
@ConditionalOnProperty(name = { "spring.parallel-proxy.server", "spring.parallel-proxy.group" })
@Configuration
public class ProxyRegisterConfiguration {
	@Value("${spring.parallel-proxy.server:http://localhost:19999/ProxyController/registerInst}")
	private String parallelProxyServer;

	@Value("${spring.application.name}")
	private String appName;

	@Value("${spring.cloud.nacos.discovery.metadata.apiVersion}")
	private String apiVersion;

	@Value("${server.port}")
	private int port;

	@Value("${spring.parallel-proxy.group:default}")
	private String group;

	@Value("${spring.parallel-proxy.heartbeat:3}")
	private int heartbeat;

	private ScheduledExecutorService es = Executors.newSingleThreadScheduledExecutor();

	@Resource(name = "noLogRestTemplate")
	private RestTemplate restTemplate;

	@Autowired
	private InetUtils inetUtils;

	private InetUtils.HostInfo hostInfo;

	@PostConstruct
	public void init() {
		hostInfo = inetUtils.findFirstNonLoopbackHostInfo();
	}

	@EventListener
	public void event(ApplicationStartedEvent event) {
		ServiceInst serviceInst = new ServiceInst();
		serviceInst.setAppName(appName);
		serviceInst.setGroup(group);
		serviceInst.setHost(hostInfo.getIpAddress());
		serviceInst.setPort(port);
		serviceInst.setApiVersion(apiVersion);

		log.info("register parallel proxy scheduler serviceInst:{}", serviceInst);
		es.scheduleWithFixedDelay(() -> {
			Date date = new Date();
			try {
				HttpHeaders headers = new HttpHeaders();
				headers.setContentType(MediaType.APPLICATION_JSON);
				headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
				HttpEntity<ServiceInst> entity = new HttpEntity<>(serviceInst, headers);
				ResponseEntity<Result<String>> exchange = restTemplate
						.exchange(parallelProxyServer, HttpMethod.POST, entity, new ParameterizedTypeReference<Result<String>>() {});
				Result<String> result = exchange.getBody();
				if (result.isSuccess()) {
					log.debug("register request {} ,response {} used time {} ms!", serviceInst, result, DateUtil.getUseTime(date));
				} else {
					log.error("register request {} ,response {}  error used time {} ms!", serviceInst, result, DateUtil.getUseTime(date));
				}
			} catch (Exception e) {
				log.debug("register request {} scheduler error used time {} ms!", serviceInst, DateUtil.getUseTime(date), e);
			}
		}, 0, heartbeat, TimeUnit.SECONDS);
	}

	@PreDestroy
	public void destroy() {
		StopUtil.stopES(es);
	}
}
