package com.hotent.base.util;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * 获取上下文bean
 * 
 * @开发公司：广州宏天软件股份有限公司
 * @作者：heyifan
 * @邮箱：heyf@jee-soft.cn
 * @创建时间：2018年4月3日
 */
@Component
public class AppUtil implements ApplicationContextAware {
	
	
	private static String serverPort;
	 
	@Value("${server.port}")
	public String applicationPort;
 
    @PostConstruct
    public void setPort() {
    	serverPort = this.applicationPort;
    }
    
	public static String getServerPort() {
		return serverPort;
	}


	protected static final Logger LOGGER = LoggerFactory.getLogger(AppUtil.class);

	private static ApplicationContext context;

	@Override
	public void setApplicationContext(ApplicationContext _context)
			throws BeansException {
		context = _context;
	}
	
	/**
	 * 获取spring容器上下文。 
	 * @return  ApplicationContext
	 */
	public static ApplicationContext getApplicaitonContext(){
		return context;
	}

	/**
	 * 根据beanId获取配置在系统中的对象实例。
	 * 
	 * @param beanId
	 * @return Object
	 * @exception
	 * @since 1.0.0
	 */
	public static Object getBean(String beanId) {
		try{
			return context.getBean(beanId);
		}
		catch(Exception ex){
			LOGGER.debug("getBean:" + beanId +"," + ex.getMessage());
		}
		return null;
	}
	
	/**
	 * 获取所有bean 
	 * @param <T>
	 * @param type
	 * @return
	 */
	public static <T> Map<String,T> getBeansOfType(Class<T> type){
		return context.getBeansOfType(type);
	}

	/**
	 * 获取Spring容器的Bean
	 * 
	 * @param beanClass
	 * @return T
	 * @exception
	 * @since 1.0.0
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(Class<T> beanClass) {
		 T  bean = null;
		try{
			  bean= context.getBean(beanClass);
		}
		catch(Exception ex){
            try {
                if ( beanClass !=null) {
                    String beanName= beanClass.getSimpleName();
                    String beanId = beanName.substring(0, 1).toLowerCase()+beanName.substring(1);
                    bean = (T) context.getBean(beanId);
                }
            } catch (BeansException e) {
            	LOGGER.debug("getBean:" + beanClass +"," + ex.getMessage());
            }
        }
		return bean;
	}
	
	/**
	 * 根据指定的接口或基类获取实现类列表。
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List<Class> getImplClass(Class clazz) throws Exception{
		List<Class> list=new ArrayList<Class>();
		
		Map map= context.getBeansOfType(clazz);
		for(Object obj : map.values()){
			String name=obj.getClass().getName();
			int pos=name.indexOf("$$");
			if(pos>0){
				name=name.substring(0,name.indexOf("$$")) ; 
			}
			Class cls= forName(name);
			
			list.add(cls);
		}
		return list;
	}


	@SuppressWarnings("rawtypes")
	public static Class forName(String className) throws Exception {
		Class cls = null;
		try {
			cls = Class.forName(className);
		} catch (Exception e) {
			cls = ExtendClassLoader.getClassByName(className);
			if (cls == null) {
				throw e;
			}
		}
		return cls;
	}

	/**
	 * 获取接口的实现类实例。
	 * @param clazz
	 * @return
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map<String,Object> getImplInstance(Class clazz) throws ClassNotFoundException{
		Map map= context.getBeansOfType(clazz);
		return map;
	}
	
	/**
	 * 发布事件。
	 * @param event 
	 * void
	 */
	public static void publishEvent(ApplicationEvent event){
		if(context!=null){
			context.publishEvent(event);
		}
	}
	
	/**
	 * 发布事件
	 * @param var
	 */
	public static void publishEvent(Object var){
		if(context!=null){
			context.publishEvent(var);
		}
	}
	
	/**
	 * 获取Classpath物理路径
	 * @return
	 */
	public static String getClasspath(){
		 String classPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
		 String rootPath  = "";
		  //windows下
		  if("\\".equals(File.separator)){   
		   rootPath  = classPath.substring(1);
		   rootPath = rootPath.replace("/", "\\");
		  }
		  //linux下
		  if("/".equals(File.separator)){   
		   rootPath  = classPath.substring(1);
		   rootPath = rootPath.replace("\\", "/");
		  }
		  return rootPath;
	}
	/**
	 * 由于在过滤器中无法直接通过Autowired获取Bean,因此需要通过spring上下文来获取IOC管理的实体类
	 * 此处主要是用于  RedisUserUtils
	 * @param clazz
	 * @param request
	 * @param <T>
	 * @return
	 */
	public static  <T> T getBean(Class<T> clazz, HttpServletRequest request){
		WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
		return applicationContext.getBean(clazz);
	}
}
