package com.inkasso.auth.service;

import com.inkasso.auth.annotation.AuthenticationType;
import com.inkasso.auth.properties.NotLoginUrl;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 张超
 * @date 2021/11/2
 */
public abstract class AuthenticationTypeService implements ApplicationContextAware,
    ApplicationListener<ContextRefreshedEvent> {

  private Map<String, AbstractAuthentication> map = new HashMap<>();

  private List<String> whiteUrl;

  private ApplicationContext applicationContext;

  @Override
  public final void setApplicationContext(ApplicationContext applicationContext)
      throws BeansException {
    this.applicationContext = applicationContext;
  }

  private void init() {
    NotLoginUrl notLoginUrl = applicationContext.getBean(NotLoginUrl.class);
    if (notLoginUrl != null) {
      whiteUrl = notLoginUrl.getUrl();
    }
  }


  private void initAuthenticationModel() {
    Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(
        AuthenticationType.class);
    if (beansWithAnnotation != null && beansWithAnnotation.size() > 0) {
      Collection<Object> values = beansWithAnnotation.values();
      for (Object obj : values) {
        AuthenticationType anno = obj.getClass().getAnnotation(AuthenticationType.class);
        map.put(anno.type(), (AbstractAuthentication) obj);
      }
    }
  }


  private void initMapping() {
    RequestMappingHandlerMapping bean = applicationContext.getBean(
        RequestMappingHandlerMapping.class);
    //registMapping(bean);
  }


//  private void registMapping(RequestMappingHandlerMapping requestMappingHandlerMapping) {
//    Method[] methods = PermissionController.class.getMethods();
//    for (Method targetMethod : methods) {
//      RequestMappingInfo info = getRequestMappingInfo(targetMethod,
//          PermissionController.class, requestMappingHandlerMapping);
//      //默认开启，如果额外配置了关闭，则取消注册
//      if (info != null) {
//        requestMappingHandlerMapping.registerMapping(info, "permissionController",
//            targetMethod);
//      }
//    }
//  }


  private RequestMappingInfo getRequestMappingInfo(Method targetMethod, Class<?> clazz,
      RequestMappingHandlerMapping requestMappingHandlerMapping) {
    try {
      Method wrapMethod = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class,
          "getMappingForMethod", Method.class, Class.class);
      if (wrapMethod != null) {
        wrapMethod.setAccessible(true);
        Object result = wrapMethod.invoke(requestMappingHandlerMapping, targetMethod, clazz);
        return (RequestMappingInfo) result;
      }
    } catch (Exception e) {

    }
    return null;
  }

  protected AbstractAuthentication getByType(String type) {
    return map.get(type);
  }

  protected List<String> getWhiteUrl() {
    return whiteUrl;
  }

  @Override
  public void onApplicationEvent(ContextRefreshedEvent event) {
    init();
    initAuthenticationModel();
  }
}
