/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.dubbo.apidocs.core;

import org.apache.dubbo.apidocs.core.beans.ApiCacheItem;
import org.apache.dubbo.apidocs.core.beans.ApiParamsCacheItem;
import org.apache.dubbo.apidocs.core.beans.ModuleCacheItem;
import org.apache.dubbo.apidocs.core.beans.HtmlTypeEnum;
import org.apache.dubbo.apidocs.core.beans.ParamBean;
import org.apache.dubbo.apidocs.core.providers.DubboDocProviderImpl;
import org.apache.dubbo.apidocs.core.providers.IDubboDocProvider;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.apidocs.annotations.ApiModule;
import org.apache.dubbo.apidocs.annotations.ApiDoc;
import org.apache.dubbo.apidocs.annotations.RequestParam;
import org.apache.dubbo.apidocs.utils.ClassTypeUtil;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Import;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.dubbo.apidocs.core.Constants.DOT;
import static org.apache.dubbo.apidocs.core.Constants.METHOD_PARAM_INDEX_BOUNDARY_LEFT;
import static org.apache.dubbo.apidocs.core.Constants.METHOD_PARAM_INDEX_BOUNDARY_RIGHT;
import static org.apache.dubbo.apidocs.core.Constants.METHOD_PARAMETER_SEPARATOR;
import static org.apache.dubbo.apidocs.core.Constants.SKIP_FIELD_SERIALVERSIONUID;
import static org.apache.dubbo.apidocs.core.Constants.SKIP_FIELD_THIS$0;
import static org.apache.dubbo.apidocs.core.Constants.ALLOWABLE_BOOLEAN_TRUE;
import static org.apache.dubbo.apidocs.core.Constants.ALLOWABLE_BOOLEAN_FALSE;
import static org.apache.dubbo.apidocs.core.Constants.METHOD_NAME_NAME;

/**
 * Scan and process dubbo doc annotations.
 */
@Import({DubboDocProviderImpl.class})
public class DubboApiDocsAnnotationScanner implements ApplicationListener<ApplicationReadyEvent> {

    private static final Logger LOG = LoggerFactory.getLogger(DubboApiDocsAnnotationScanner.class);

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private ApplicationConfig application;

    @Autowired
    private RegistryConfig registry;

    @Autowired
    private ProtocolConfig protocol;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        // Register dubbo doc provider
        IDubboDocProvider dubboDocProvider = applicationContext.getBean(IDubboDocProvider.class);
        exportDubboService(IDubboDocProvider.class, dubboDocProvider, false);

        LOG.info("================= Dubbo API Docs--Start scanning and processing doc annotations ================");

        Map<String, Object> apiModules = applicationContext.getBeansWithAnnotation(ApiModule.class);
        apiModules.forEach((key, apiModuleTemp) -> {
            Class<?> apiModuleClass;
            if (AopUtils.isAopProxy(apiModuleTemp)) {
                apiModuleClass = AopUtils.getTargetClass(apiModuleTemp);
            } else {
                apiModuleClass = apiModuleTemp.getClass();
            }
            ApiModule moduleAnn = apiModuleClass.getAnnotation(ApiModule.class);
            if (!apiModuleClass.isAnnotationPresent(Service.class) && !apiModuleClass.isAnnotationPresent(DubboService.class)) {
                LOG.warn("【Warning】" + apiModuleClass.getName() + " @ApiModule annotation is used, " +
                        "but it is not a dubbo provider (without " + Service.class.getName() + " or " +
                        DubboService.class.getName() + " annotation)");
                return;
            }
            boolean async;
            String apiVersion;
            String apiGroup;
            if (apiModuleClass.isAnnotationPresent(Service.class)) {
                Service dubboService = apiModuleClass.getAnnotation(Service.class);
                async = dubboService.async();
                apiVersion = dubboService.version();
                apiGroup = dubboService.group();
            } else {
                DubboService dubboService = apiModuleClass.getAnnotation(DubboService.class);
                async = dubboService.async();
                apiVersion = dubboService.version();
                apiGroup = dubboService.group();
            }
            apiVersion = applicationContext.getEnvironment().resolvePlaceholders(apiVersion);
            apiGroup = applicationContext.getEnvironment().resolvePlaceholders(apiGroup);
            ModuleCacheItem moduleCacheItem = new ModuleCacheItem();
            DubboApiDocsCache.addApiModule(moduleAnn.apiInterface().getCanonicalName(), moduleCacheItem);
            //module name
            moduleCacheItem.setModuleDocName(moduleAnn.value());
            //interface name containing package path
            moduleCacheItem.setModuleClassName(moduleAnn.apiInterface().getCanonicalName());
            //module version
            moduleCacheItem.setModuleVersion(apiVersion);
            //module group
            moduleCacheItem.setModuleGroup(apiGroup);

            Method[] apiModuleMethods = apiModuleClass.getMethods();
            // API basic information list in module cache
            List<ApiCacheItem> moduleApiList = new ArrayList<>(apiModuleMethods.length);
            moduleCacheItem.setModuleApiList(moduleApiList);
            for (Method method : apiModuleMethods) {
                if (method.isAnnotationPresent(ApiDoc.class)) {
                    processApiDocAnnotation(method, moduleApiList, moduleAnn, async, moduleCacheItem, apiVersion, apiGroup);
                }
            }
        });
        LOG.info("================= Dubbo API Docs-- doc annotations scanning and processing completed ================");
    }

    private void processApiDocAnnotation(Method method, List<ApiCacheItem> moduleApiList, ApiModule moduleAnn,
                                         boolean async, ModuleCacheItem moduleCacheItem, String apiVersion, String apiGroup) {

        ApiDoc dubboApi = method.getAnnotation(ApiDoc.class);

        // API basic information in API list in module
        ApiCacheItem apiListItem = new ApiCacheItem();
        moduleApiList.add(apiListItem);
        //API method name
        apiListItem.setApiName(method.getName());
        //API name
        apiListItem.setApiDocName(dubboApi.value());
        // API description
        apiListItem.setDescription(dubboApi.description());
        //API version
        apiListItem.setApiVersion(apiVersion);
        //API group
        apiListItem.setApiGroup(apiGroup);
        //Description of API return data
        apiListItem.setApiRespDec(dubboApi.responseClassDescription());

        // API details in cache, contain interface parameters and response information
        ApiCacheItem apiParamsAndResp = new ApiCacheItem();
        DubboApiDocsCache.addApiParamsAndResp(
                moduleAnn.apiInterface().getCanonicalName() + DOT + method.getName(), apiParamsAndResp);

        Class<?>[] argsClass = method.getParameterTypes();
        Annotation[][] argsAnns = method.getParameterAnnotations();
        Parameter[] parameters = method.getParameters();
        Type[] parametersTypes = method.getGenericParameterTypes();
        List<ApiParamsCacheItem> paramList = new ArrayList<>(argsClass.length);
        apiParamsAndResp.setAsync(async);
        apiParamsAndResp.setApiName(method.getName());
        apiParamsAndResp.setApiDocName(dubboApi.value());
        apiParamsAndResp.setApiVersion(apiVersion);
        apiParamsAndResp.setApiGroup(apiGroup);
        apiParamsAndResp.setApiRespDec(dubboApi.responseClassDescription());
        apiParamsAndResp.setDescription(dubboApi.description());
        apiParamsAndResp.setApiModelClass(moduleCacheItem.getModuleClassName());
        apiParamsAndResp.setParams(paramList);
        apiParamsAndResp.setResponse(ClassTypeUtil.calss2Json(method.getGenericReturnType(), method.getReturnType()));
        StringBuilder methodParamInfoSb = new StringBuilder();
        for (int i = 0; i < argsClass.length; i++) {
            Class<?> argClass = argsClass[i];
            Type parameterType = parametersTypes[i];
            methodParamInfoSb.append(METHOD_PARAM_INDEX_BOUNDARY_LEFT).append(i)
                    .append(METHOD_PARAM_INDEX_BOUNDARY_RIGHT).append(argClass.getCanonicalName());
            if (i + 1 < argsClass.length) {
                methodParamInfoSb.append(METHOD_PARAMETER_SEPARATOR);
            }
            Annotation[] argAnns = argsAnns[i];
            ApiParamsCacheItem paramListItem = new ApiParamsCacheItem();
            paramList.add(paramListItem);
            paramListItem.setParamType(argClass.getCanonicalName());
            paramListItem.setParamIndex(i);
            RequestParam requestParam = null;
            // Handling @RequestParam annotations on parameters
            for (Annotation ann : argAnns) {
                if (ann instanceof RequestParam) {
                    requestParam = (RequestParam) ann;
                }
            }
            ParamBean paramBean = this.processHtmlType(argClass, requestParam, null);
            Parameter methodParameter = parameters[i];
            if (paramBean == null) {
                // Not a basic type, handling properties in method parameters
                List<ParamBean> apiParamsList = processField(argClass, parameterType, methodParameter);
                if (apiParamsList != null && !apiParamsList.isEmpty()) {
                    paramListItem.setParamInfo(apiParamsList);
                }
            } else {
                // Is the basic type
                paramListItem.setName(methodParameter.getName());
                paramListItem.setHtmlType(paramBean.getHtmlType().name());
                paramListItem.setAllowableValues(paramBean.getAllowableValues());
                if (requestParam != null) {
                    // Handling requestparam annotations on parameters
                    paramListItem.setDocName(requestParam.value());
                    paramListItem.setDescription(requestParam.description());
                    paramListItem.setExample(requestParam.example());
                    paramListItem.setDefaultValue(requestParam.defaultValue());
                    paramListItem.setRequired(requestParam.required());
                } else {
                    paramListItem.setRequired(false);
                }

                if (HtmlTypeEnum.TEXT_AREA.name().equals(paramListItem.getHtmlType())) {
                    List<ParamBean> apiParamsList = processField(argClass, parameterType, methodParameter);
                    paramListItem.setAllowableValues(apiParamsList.get(0).getAllowableValues());
                    paramListItem.setSubParamsJson(apiParamsList.get(0).getSubParamsJson());
                }
            }
        }
        apiParamsAndResp.setMethodParamInfo(methodParamInfoSb.toString());
    }

    /**
     * For the attributes in the method parameters, only one layer is processed.
     * The deeper layer is directly converted to JSON, and the deeper layer is up to 5 layers
     */
    private List<ParamBean> processField(Class<?> argClass, Type parameterType, Parameter parameter) {
        Map<String, String> genericTypeAndNamesMap;
        if (parameterType instanceof ParameterizedTypeImpl) {
            ParameterizedTypeImpl parameterTypeImpl = (ParameterizedTypeImpl) parameterType;
            TypeVariable<? extends Class<?>>[] typeVariables = parameterTypeImpl.getRawType().getTypeParameters();
            Type[] actualTypeArguments = parameterTypeImpl.getActualTypeArguments();
            genericTypeAndNamesMap = new HashMap<>(typeVariables.length);
            for (int i = 0; i < typeVariables.length; i++) {
                genericTypeAndNamesMap.put(typeVariables[i].getTypeName(), actualTypeArguments[i].getTypeName());
            }
        } else {
            genericTypeAndNamesMap = Collections.EMPTY_MAP;
        }

        List<ParamBean> apiParamsList = new ArrayList(16);
        // get all fields
        List<Field> allFields = ClassTypeUtil.getAllFields(null, argClass);
        if (allFields.size() > 0) {
            for (Field field : allFields) {
                if (SKIP_FIELD_SERIALVERSIONUID.equals(field.getName()) || SKIP_FIELD_THIS$0.equals(field.getName())) {
                    continue;
                }
                ParamBean paramBean = new ParamBean();
                paramBean.setName(field.getName());
                String genericTypeName = genericTypeAndNamesMap.get(field.getGenericType().getTypeName());
                Class<?> genericType = null;
                if (StringUtils.isBlank(genericTypeName)) {
                    paramBean.setJavaType(field.getType().getCanonicalName());
                } else {
                    paramBean.setJavaType(genericTypeName);
                    genericType = ClassTypeUtil.makeClass(genericTypeName);
                }
                RequestParam requestParam = null;
                if (field.isAnnotationPresent(RequestParam.class)) {
                    // Handling @RequestParam annotations on properties
                    requestParam = field.getAnnotation(RequestParam.class);
                    paramBean.setDocName(requestParam.value());
                    paramBean.setRequired(requestParam.required());
                    paramBean.setDescription(requestParam.description());
                    paramBean.setExample(requestParam.example());
                    paramBean.setDefaultValue(requestParam.defaultValue());
                } else {
                    paramBean.setRequired(false);
                }

                ParamBean tempParamBean = this.processHtmlType(null == genericType ?
                        field.getType() : genericType, requestParam, paramBean);
                if (tempParamBean == null || HtmlTypeEnum.TEXT_AREA.equals(tempParamBean.getHtmlType())) {
                    Object objResult;
                    if (null == genericType) {
                        objResult = ClassTypeUtil.initClassTypeWithDefaultValue(
                                field.getGenericType(), field.getType(), 0, genericTypeAndNamesMap);
                    } else {
                        objResult = ClassTypeUtil.initClassTypeWithDefaultValue(
                                ClassTypeUtil.makeParameterizedType(genericTypeName), genericType, 0,
                                true, genericTypeAndNamesMap);
                    }
                    if (!ClassTypeUtil.isBaseType(objResult)) {
                        paramBean.setHtmlType(HtmlTypeEnum.TEXT_AREA);
                        paramBean.setSubParamsJson(JSON.toJSONString(objResult, ClassTypeUtil.FAST_JSON_FEATURES));
                    }
                }
                apiParamsList.add(paramBean);
            }
        } else {
            ParamBean paramBean = new ParamBean();
            paramBean.setName(parameter.getName());
            paramBean.setJavaType(argClass.getCanonicalName());
            RequestParam requestParam = null;
            if (parameter.isAnnotationPresent(RequestParam.class)) {
                // Handling @RequestParam annotations on properties
                requestParam = parameter.getAnnotation(RequestParam.class);
                paramBean.setDocName(requestParam.value());
                paramBean.setRequired(requestParam.required());
                paramBean.setDescription(requestParam.description());
                paramBean.setExample(requestParam.example());
                paramBean.setDefaultValue(requestParam.defaultValue());
            } else {
                paramBean.setRequired(false);
            }

            Object objResult = ClassTypeUtil.initClassTypeWithDefaultValue(
                    parameterType, argClass, 0, genericTypeAndNamesMap);
            if (!ClassTypeUtil.isBaseType(objResult)) {
                paramBean.setHtmlType(HtmlTypeEnum.TEXT_AREA);
                paramBean.setSubParamsJson(JSON.toJSONString(objResult, ClassTypeUtil.FAST_JSON_FEATURES));
            }
            apiParamsList.add(paramBean);
        }
        return apiParamsList;
    }

    /**
     * Determine what HTML form elements to use.
     *
     * @param classType  classType
     * @param annotation annotation
     * @param param      param
     * @return org.apache.dubbo.apidocs.core.beans.ParamBean
     */
    private ParamBean processHtmlType(Class<?> classType, RequestParam annotation, ParamBean param) {
        if (param == null) {
            param = new ParamBean();
        }
        if (annotation != null) {
            param.setAllowableValues(annotation.allowableValues());
        }
        // Is there any allowed values
        boolean hasAllowableValues = (param.getAllowableValues() != null && param.getAllowableValues().length > 0);
        // Processed or not
        boolean processed = false;
        if (Integer.class.isAssignableFrom(classType) || int.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.NUMBER_INTEGER);
            processed = true;
        } else if (Byte.class.isAssignableFrom(classType) || byte.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.TEXT_BYTE);
            processed = true;
        } else if (Long.class.isAssignableFrom(classType) || long.class.isAssignableFrom(classType) ||
                BigDecimal.class.isAssignableFrom(classType) || BigInteger.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.NUMBER_INTEGER);
            processed = true;
        } else if (Double.class.isAssignableFrom(classType) || double.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.NUMBER_DECIMAL);
            processed = true;
        } else if (Float.class.isAssignableFrom(classType) || float.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.NUMBER_DECIMAL);
            processed = true;
        } else if (String.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.TEXT);
            processed = true;
        } else if (Character.class.isAssignableFrom(classType) || char.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.TEXT_CHAR);
            processed = true;
        } else if (Short.class.isAssignableFrom(classType) || short.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.NUMBER_INTEGER);
            processed = true;
        } else if (Date.class.isAssignableFrom(classType) || LocalDateTime.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.DATETIME_SELECTOR);
            processed = true;
        } else if (LocalDate.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.DATE_SELECTOR);
            processed = true;
        } else if (classType.isArray() || Collection.class.isAssignableFrom(classType) ||
                Map.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.TEXT_AREA);
            processed = true;
        }

        if (processed) {
            // Processed, time to return
            if (hasAllowableValues) {
                // Allowed values has value, change to select
                param.setHtmlType(HtmlTypeEnum.SELECT);
            }
            return param;
        }

        // haven't dealt with it. Go on
        if (Boolean.class.isAssignableFrom(classType) || boolean.class.isAssignableFrom(classType)) {
            param.setHtmlType(HtmlTypeEnum.SELECT);
            // Boolean can only be true / false. No matter what the previous allowed value is, it is forced to replace
            param.setAllowableValues(new String[]{ALLOWABLE_BOOLEAN_TRUE, ALLOWABLE_BOOLEAN_FALSE});
            processed = true;
        } else if (Enum.class.isAssignableFrom(classType)) {
            // process enum
            param.setHtmlType(HtmlTypeEnum.SELECT);

            Object[] enumConstants = classType.getEnumConstants();
            String[] enumValues = new String[enumConstants.length];
            try {
                Method getNameMethod = classType.getMethod(METHOD_NAME_NAME);
                for (int i = 0; i < enumConstants.length; i++) {
                    Object obj = enumConstants[i];
                    enumValues[i] = (String) getNameMethod.invoke(obj);
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                LOG.error(e.getMessage(), e);
            }

            if (!hasAllowableValues) {
                // If there is no optional value, it is taken from the enumeration.
                param.setAllowableValues(enumValues);
            } else {
                // If there has allowable values, it is necessary to check whether the allowable values matches the enumeration.
                boolean checkSuccess = true;
                String[] allowableValues = param.getAllowableValues();
                for (String allowableValue : allowableValues) {
                    for (String enumValue : enumValues) {
                        if (!StringUtils.equals(enumValue, allowableValue)) {
                            checkSuccess = false;
                        }
                    }
                }
                if (!checkSuccess) {
                    LOG.error("The allowed value in the @RequestParam annotation does not match the " +
                            "annotated enumeration " + classType.getCanonicalName() + ", please check!");
                }
            }
            processed = true;
        }
        if (processed) {
            return param;
        }
        return null;
    }

    /**
     * export dubbo service for dubbo doc
     */
    private <I, T> void exportDubboService(Class<I> serviceClass, T serviceImplInstance, boolean async) {
        ServiceConfig<T> service = new ServiceConfig<>();
        service.setApplication(application);
        service.setRegistry(registry);
        service.setProtocol(protocol);
        service.setInterface(serviceClass);
        service.setRef(serviceImplInstance);
        service.setAsync(async);
//        service.setVersion("1.0.0");
        service.export();
    }

}
