package com.pictc.utils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;

/**
 * @Description springbean 工具类型
 * @author zhangfucai
 * @Date 2023年6月29日 下午3:47:01
 * @version 1.0.0
 */
public class SpringTools implements ApplicationContextAware,EnvironmentAware{
	
	public static final String CONFIG_KEY_APPLICATION = "spring.application.name";
	
	public static final String CONFIG_KEY_PROFILE = "spring.profiles.active";
	
	public static final String CONFIG_PROD_VALUE = "prod";
	
	private static ApplicationContext context;
	
	private static Environment environment;

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		SpringTools.context = context;
	}
	
	@Override
	public void setEnvironment(Environment environment) {
		SpringTools.environment = environment;
	}
	
	
	public static ConfigurableApplicationContext logStarter(Class<?> appClass,String[] args) {
		long start = System.currentTimeMillis();
		SpringApplicationBuilder builder = new SpringApplicationBuilder(appClass);
		return logStarter(start, builder.headless(false).run(args));
	}
	
	public static ConfigurableApplicationContext logStarter(long start,ConfigurableApplicationContext context) {
		ConfigurableEnvironment env = context.getEnvironment();
		Integer _port = env.getProperty("server.port",int.class);
		int port = _port==null?8080:_port.intValue();
		String profile = env.getProperty(CONFIG_KEY_PROFILE,"dev");
		Map<String,String> values = new HashMap<String, String>();
		ServerProperties server = context.getBean(ServerProperties.class);
		String path = getContextPath(server.getServlet().getContextPath());
		String portPath = port==80?"":":"+port;
		values.put("${serverName}", env.getProperty(CONFIG_KEY_APPLICATION));
		values.put("${profiles}", profile);
		values.put("${time}",String.valueOf((System.currentTimeMillis()-start)/1000));
		values.put("${url}", "http://localhost"+portPath+path);
		printBanner(values);
		return context;
	}
	
	/**
	 * @param values
	 */
	private static void printBanner(Map<String, String> values) {
		ScanFile.scan("t-banner.txt",new ScanFileFilter() {
			
			private boolean ready = false;
			
			@Override
			public void accept(InputStream in) {
				if(!ready) {
					ready = true;
				}else {
					return;
				}
				BufferedReader  reader = null;
				try {
					reader = new BufferedReader(new InputStreamReader(in));
		            String line = null;
		            while ((line = reader.readLine()) != null) {
		            	for (String key : values.keySet()) {
		            		line = line.replace(key, values.get(key));
						}
		                System.out.println(line);
		            }
		        } catch (Exception e) {
		        }finally {
		           IoUtils.closeQuietly(reader);
		        }
			}
		});
	}

	public static String getLocalIp() {
		try {
			return InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			throw new RuntimeException("获取本地ip异常", e);
		}
	}
	
	private static String getContextPath(String path) {
		if(!StringUtils.isEmpty(path)) {
			if(!path.startsWith("/")) {
				path = "/"+path;
			}
			if(path.endsWith("/")) {
				path = path.substring(0,path.length()-1);
			}
			return path;
		}
		return "";
	}
	
	
	public static <T>T getBean(Class<T> clazz){
		return context.getBean(clazz);
	}
	
	
	@SuppressWarnings("unchecked")
	public static <T>T getBean(String name){
		if(context.containsBean(name)) {
			return (T) context.getBean(name);
		}
		return null;
	}
	
	public static <T>Map<String, T> getBeansOfType(Class<T> clazz){
		return context.getBeansOfType(clazz);
	}
	
	public static <T>List<T> getBeans(Class<T> clazz){
		return getBeans(clazz, false);
	}
	
	public static <T>List<T> getBeans(Class<T> clazz,boolean sort){
		List<T> beans = CollectionUtils.newArrayList();
		Map<String, T> maps = getBeansOfType(clazz);
		if(maps!=null && maps.isEmpty()==false) {
			beans = new ArrayList<T>(maps.values());
			if(sort) AnnotationAwareOrderComparator.sort(beans);
		}
		return beans;
	}

	public static <T>T getProperty(String key,Class<T> targetType,T defaultValue) {
		return environment.getProperty(key, targetType, defaultValue);
	}
	
	public static <T>T getProperty(String key,Class<T> targetType) {
		return environment.getProperty(key, targetType);
	}
	
	public static String getProperty(String key) {
		return environment.getProperty(key);
	}


}
