package com.boco.nbd.wios.microservice;


import com.boco.nbd.framework.parent.microservice.EnableMicroserviceApplication;
import com.boco.nbd.framework.parent.microservice.FrameworkMicroserviceApplication;
import com.boco.nbd.wios.flow.sms.aliyun.AliyunSendHandler;
import com.boco.nbd.wios.flow.sms.aliyun.properties.AliyunProperties;
import com.dtflys.forest.springboot.annotation.ForestScan;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ihidea.component.api.v2.annotation.EnableApiV2;
import com.ihidea.component.datastore.FileServlet;
import com.ihidea.core.support.SpringContextLoader;
import com.ihidea.core.support.orm.mybatis3.interceptor.dialect.DialectInterceptor;
import com.ihidea.core.support.pageLimit.PageLimitHolderFilter;
import com.ihidea.core.support.servlet.ServletHolderFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;
import java.util.EventListener;

/**
 * @author:cao hai
 * @date:2022/6/13 14:35
 * @version:V1.0
 * @description:Application
 * @modify:
 */
@EnableMicroserviceApplication
@EnableAspectJAutoProxy
@EnableConfigurationProperties(AliyunProperties.class)
@EnableApiV2
@EnableAsync
@EnableTransactionManagement
@ForestScan(basePackages = "com.boco.nbd.wios.manage.client")
public class Application extends FrameworkMicroserviceApplication {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        FrameworkMicroserviceApplication.getApplication().start();
    }

    /**
     * 允许跨域的filter
     *
     * @return Filter
     */
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
        CorsConfigurationSource configSource = request -> {
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowCredentials(true);
            config.addAllowedOrigin("*");
            config.addAllowedHeader("*");
            config.addAllowedMethod("*");
            return config;
        };

        registrationBean.setFilter(new CorsFilter(configSource));
        registrationBean.setUrlPatterns(Arrays.asList("*"));
        // 支持cors跨域的filter必须放第一个
        registrationBean.setOrder(0);
        return registrationBean;
    }


    /**
     * 注册FileServlet,实现文件下载接口,适用于本地文件存储
     *
     * @return Servlet
     */
    @Bean
    public ServletRegistrationBean<FileServlet> fileServlet() {
        ServletRegistrationBean<FileServlet> bean = new ServletRegistrationBean<>(new FileServlet(), "/download/*");
        bean.setOrder(20);
        return bean;
    }

    /**
     * 注册ServletHolderFilter,实现在请求线程的任何代码模块都能获得request和response(不推荐)
     *
     * @return Filter
     */
    @Bean
    public FilterRegistrationBean<ServletHolderFilter> servletHolderFilter() {
        FilterRegistrationBean<ServletHolderFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new ServletHolderFilter());
        registrationBean.setUrlPatterns(Arrays.asList(new String[]{"*.do", "/api/*"}));
        registrationBean.setOrder(40);
        return registrationBean;
    }

    /**
     * 注册PageLimitHolderFilter,实现自动化分页
     *
     * @return Filter
     */
    @Bean
    public FilterRegistrationBean<PageLimitHolderFilter> pageLimitFilter() {
        FilterRegistrationBean<PageLimitHolderFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new PageLimitHolderFilter());
        registrationBean.setUrlPatterns(Arrays.asList(new String[]{"*.do", "/api/*"}));
        registrationBean.setOrder(50);
        return registrationBean;
    }

    /**
     * 注册spring上下文监听器
     *
     * @return Listener
     */
    @Bean
    public ServletListenerRegistrationBean<EventListener> springContextLoaderListener() {
        ServletListenerRegistrationBean<EventListener> registrationBean = new ServletListenerRegistrationBean<>();
        registrationBean.setListener(new SpringContextLoader());
        return registrationBean;
    }

    /**
     * 注册mybatis分页插件
     *
     * @return bean
     */
    @Bean
    public DialectInterceptor mybatisPageLimit() {
        DialectInterceptor.getDialect();
        return new DialectInterceptor();
    }

    /**
     * 构造阿里云发送处理.
     *
     * @param properties     配置对象
     * @return 阿里云发送处理
     */
    @Bean
    @Conditional(AliyunSendHandlerCondition.class)
    public AliyunSendHandler aliyunSendHandler(AliyunProperties properties, ObjectMapper objectMapper) {
        return new AliyunSendHandler(properties, objectMapper);
    }

    public static class AliyunSendHandlerCondition implements Condition {
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            Boolean enable = context.getEnvironment().getProperty("sms.aliyun.enable", Boolean.class);
            return enable == null || enable;
        }
    }

}