package com.redant.core.interceptor;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.ClassScaner;
import com.redant.core.anno.Order;
import com.redant.core.common.constants.CommonConstants;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author houyi
 **/
public class InterceptorProvider {

    private static volatile boolean loaded = false;

    private static volatile InterceptorBuilder builder = null;

    public static List<Interceptor> getInterceptors(){
        // 优先获取用户自定义的 InterceptorBuilder 构造的 Interceptor
        if(!loaded){
            synchronized (InterceptorProvider.class) {
                if(!loaded) {
                    Set<Class<?>> builders = ClassScaner.scanPackageBySuper(CommonConstants.INTERCEPTOR_SCAN_PACKAGE, InterceptorBuilder.class);
                    if (CollectionUtil.isNotEmpty(builders)) {
                        try {
                            for (Class<?> cls : builders) {
                                builder = (InterceptorBuilder) cls.newInstance();
                                break;
                            }
                        } catch (IllegalAccessException | InstantiationException e) {
                            e.printStackTrace();
                        }
                    }
                    loaded = true;
                }
            }
        }
        if(builder!=null){
            return builder.build();
        }
        // 获取不到时,再扫描所有指定目录下的 Interceptor
        return InterceptorsHolder.interceptors;
    }

    static class InterceptorsHolder {

        static List<Interceptor> interceptors;

        static {
            interceptors = scanInterceptors();
        }

        private static List<Interceptor> scanInterceptors() {
            Set<Class<?>> classSet = ClassScaner.scanPackageBySuper(CommonConstants.INTERCEPTOR_SCAN_PACKAGE,Interceptor.class);
            if(CollectionUtil.isEmpty(classSet)){
                return Collections.emptyList();
            }
            List<InterceptorWrapper> wrappers = new ArrayList<>(classSet.size());
            try {
                for (Class<?> cls : classSet) {
                    Interceptor interceptor =(Interceptor)cls.newInstance();
                    insertSorted(wrappers,interceptor);
                }
            }catch (IllegalAccessException | InstantiationException e) {
                e.printStackTrace();
            }
            return wrappers.stream()
                    .map(InterceptorWrapper::getInterceptor)
                    .collect(Collectors.toList());
        }

        private static void insertSorted(List<InterceptorWrapper> list, Interceptor interceptor) {
            int order = resolveOrder(interceptor);
            int idx = 0;
            for (; idx < list.size(); idx++) {
                // 将当前interceptor插入到order值比他大的第一个interceptor前面
                if (list.get(idx).getOrder() > order) {
                    break;
                }
            }
            list.add(idx, new InterceptorWrapper(order, interceptor));
        }

        private static int resolveOrder(Interceptor interceptor) {
            if (!interceptor.getClass().isAnnotationPresent(Order.class)) {
                return Order.LOWEST_PRECEDENCE;
            } else {
                return interceptor.getClass().getAnnotation(Order.class).value();
            }
        }

        private static class InterceptorWrapper {
            private final int order;
            private final Interceptor interceptor;

            InterceptorWrapper(int order, Interceptor interceptor) {
                this.order = order;
                this.interceptor = interceptor;
            }

            int getOrder() {
                return order;
            }

            Interceptor getInterceptor() {
                return interceptor;
            }
        }
    }
}