package cn.web.config;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import cn.common.page.converter.Jackson2HttpMsg;
import cn.common.page.resolver.ResBodyWrapFactoryBean;
import cn.component.interceptor.AuthenticationInterceptor;
import cn.util.core.IsKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer 
{
	@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
	private String pattern;
	  /** 默认日期时间格式 */
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /** 默认日期格式 */
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    /** 默认时间格式 */
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
    
	@Override
	public void extendMessageConverters(List<HttpMessageConverter<?>> converters) 
	{
		MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
		//localDateTime格式化
		JavaTimeModule module = new JavaTimeModule();
		LocalDateTimeDeserializer dateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(pattern));
		LocalDateTimeSerializer dateTimeSerializer = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
		
		module.addDeserializer(LocalDateTime.class, dateTimeDeserializer);
		module.addSerializer(LocalDateTime.class, dateTimeSerializer);
		
		module.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
		module.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
		
		module.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
		module.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
		
		ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().modules(module)
				.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
				.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)//
			    .build();
		
		
		//date时间格式化
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		objectMapper.setDateFormat(new SimpleDateFormat(pattern));

		// 设置格式化内容
		converter.setObjectMapper(objectMapper);
		converters.add(0, converter);
	}
	
	@Bean
	public Jackson2HttpMsg messageConverter() 
	{
		final Jackson2HttpMsg converter = new Jackson2HttpMsg();
		final ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
		converter.setObjectMapper(objectMapper);
		return converter;
	}
	/**
	 * 响应拦截器
	 */
	@Bean
	public ResBodyWrapFactoryBean getResponseBodyWrap() {
		return new ResBodyWrapFactoryBean();
	}	

	/**跨域配置*/
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		//设置允许跨域的路由。
		registry.addMapping("/**")
		//是否发送Cookie
		.allowCredentials(true)
		//设置放行的方法"*" 
		//.allowedMethods("GET", "POST", "PUT", "DELETE")
		//或者放行全部
		.allowedMethods("*") 
		.allowCredentials(true) // 是否支持跨域用户凭证cookies
		.allowedOriginPatterns("*")
		//放行哪些原始请求头部信息
		.allowedHeaders("*")
		//暴露哪些原始请求头部信息
		.exposedHeaders("*")
		.maxAge(60); // 超时时长设置为1小时。 时间单位是秒。
	}

	@Override
	public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
	}
	
	//文件在磁盘上存放位置
	@Value("${sam.file.serverURL}")
	private String urlPrefixStr;
	@Value("${sam.file.realPath}")
	private String realPath;
	@Value("${sam.file.urlPath}")
	private String urlPath;

	/**springboot默认静态文件在 static文件夹下,引用资源不能加static,设置后要加*/
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry)
	{
		/**自定义资源映射addResourceHandlers; 比如：浏览本地图片
		 * http://www.localhost:8080/news/1650461951082.jpg
		 */
		if(IsKit.isNotNullOrEmpty(realPath) && IsKit.isNotNullOrEmpty(urlPath)) 
		{
			String[] realPathStr = realPath.split(",");
			String[] urlPathStr = urlPath.split(",");
			for(int i = 0;i < realPathStr.length;i++) {
				registry
				.addResourceHandler(urlPathStr[i])
				.addResourceLocations("file:"+realPathStr[i]);
			}
		}		
		//文档资源
		registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
		WebMvcConfigurer.super.addResourceHandlers(registry);
	}

	//可添加多个拦截地址，进入后判断是否有加注解即可
	@Override
	public void addInterceptors(InterceptorRegistry registry)
	{
		//登录拦截配置
		registry.addInterceptor(authenticationInterceptor)
		.addPathPatterns("/**");//表示拦截所有的请求

	}
	/**登录校验拦截器*/
	@Autowired
	private AuthenticationInterceptor authenticationInterceptor;

}

