package com.sdtool.common.tdoc;

import com.sdtool.common.servlet.apidoc.ApiDocServlet;
import com.sweetfish.boot.Application;
import com.sweetfish.boot.NodeHttpServer;
import com.sweetfish.boot.NodeServer;
import com.sweetfish.net.http.*;
import com.sweetfish.source.PageFlipper;
import com.sweetfish.util.ClassesUtils;
import com.sweetfish.util.Comment;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by Administrator on 2017-03-27.
 */
public class TAppDoc {

    //  private static String SPACE8 = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
    private static final String SPACE8 = "    ";
    private static final String SPACE16 = SPACE8 + SPACE8;
    private static final String SPACE24 = SPACE16 + SPACE8;

    private String appName;

    private String appHome;

    private Application application;
    private final List<TAppModule> moduleList = new ArrayList<>();

    private static final String[] simpleParamType = {"Integer", "Long", "Double", "Float", "Boolean", "String"};

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public TAppDoc bind(Application application) {
        this.application = application;
        return this;
    }

    public TAppDoc appHome(String appHome) {
        this.appHome = appHome;
        return this;
    }

    public void addModule(TAppModule module) {
        this.moduleList.add(module);
    }

    public void generateCallParam(String rootParamName, Class<?> sClass, String businessMethod, TAppMethod appMethod) {
        for (Field field : sClass.getDeclaredFields()) {
            if (Modifier.isFinal(field.getModifiers())) {
                continue;
            }
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }

            String fieldcomment = "";
            Comment comment = field.getAnnotation(Comment.class);
            if (comment != null) {
                fieldcomment = comment.value();
            }
            ApiPlace[] apiPlaces = field.getAnnotationsByType(ApiPlace.class);

            if (Arrays.stream(apiPlaces).anyMatch((place) -> businessMethod.equalsIgnoreCase(place.value()))) {
                String newRootName = StringUtils.isBlank(rootParamName) ? "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + "    --" :
                        "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + rootParamName;

                Type genericFieldType = field.getGenericType();
                if (genericFieldType instanceof ParameterizedType parameterizedType) {
                    Type rawType = parameterizedType.getRawType();
                    if(rawType == List.class) {
                        TAppCallParam callFieldParam = new TAppCallParam()
                                .setParamName(rootParamName + field.getName())
                                .setParamComment(fieldcomment + "(数组)")
                                .setParamRequired(true)
                                .setParamSrc("")
                                .setParamType(field.getType().getSimpleName());
                        appMethod.addCallParam(callFieldParam);

                        Type[] fieldArgTypes = parameterizedType.getActualTypeArguments();
                        for(Type fieldArgType : fieldArgTypes){
                            Class<?> fieldArgClass = (Class<?>) fieldArgType;


                            generateCallParam(newRootName, fieldArgClass, businessMethod, appMethod);
                        }
                    }
                } else {
                    TAppCallParam callFieldParam = new TAppCallParam()
                            .setParamName(rootParamName + field.getName())
                            .setParamComment(fieldcomment)
                            .setParamRequired(true)
                            .setParamSrc("")
                            .setParamType(field.getType().getSimpleName());
                    appMethod.addCallParam(callFieldParam);

                    //递归一下
                    final Class<?> fieldType = field.getType().isArray() ? field.getType().getComponentType() : field.getType();
                    if (ClassesUtils.isPrimitive(fieldType) || fieldType == String.class || fieldType == PageFlipper.class) {
                        continue;
                    }
                    generateCallParam(newRootName, fieldType, businessMethod, appMethod);
                }

            }
        }
    }

    public void generate() throws Exception {
        Field fieldPrefix = HttpServlet.class.getDeclaredField("_prefix");
        fieldPrefix.setAccessible(true);

        for (NodeServer node : application.getServers()) {
            if (!(node instanceof NodeHttpServer)) continue;
            HttpServer server = node.getServer();

            for (HttpServlet servlet : server.getPrepareServlet().getServlets()) {

                if (servlet == null) continue;
                if (servlet.getClass() == ApiDocServlet.class) continue;
                WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);

                if (ws == null) {
                    continue;
                }
                String prefix = (String) fieldPrefix.get(servlet);
                String[] mappings = ws.value();
                if (prefix != null && !prefix.isEmpty()) {
                    for (int i = 0; i < mappings.length; i++) {
                        mappings[i] = prefix + mappings[i];
                    }
                }
                String moduleUrl = String.join(";", mappings);
                String servletName = "未知模块";
                if (StringUtils.isNotEmpty(ws.comment())) {
                    servletName = ws.comment();
                }
                Integer moduleId = ws.moduleid();

                TAppModule module = new TAppModule()
                        .setModuleName(servletName)
                        .setUrl(moduleUrl)
                        .setModuleId(moduleId);
                addModule(module);

                final Class<? extends HttpServlet> selfClz = servlet.getClass();
                Class<? extends HttpServlet> clz = servlet.getClass();
                if (Modifier.isAbstract(clz.getModifiers())) continue;

                for (Method method : clz.getMethods()) {
                    //只识别带有httprequest和httpresponse参数的方法
                    if (method.getParameterCount() != 2) continue;
                    HttpMapping action = method.getAnnotation(HttpMapping.class);
                    if (action == null) continue;
                    //忽略不被继承的方法
                    if (!action.inherited() && selfClz != clz) continue;

                    WebApiFile[] apiFiles = method.getAnnotationsByType(WebApiFile.class);
                    if (apiFiles.length > 0) {
                        //有接口说明文件时，以文件为主，
                        //读取接口文件
                        String methodUrl = prefix + action.url();

                        String methodResult = action.result();
                        methodResult = methodResult.replace("<", " ");
                        methodResult = methodResult.replace(">", " ");
                        String finalMethodResult = methodResult;

                        for (WebApiFile apiFile : apiFiles) {
                            // 创建saxReader对象
                            SAXReader reader = new SAXReader();

                            String apiXmlFileName = appHome + File.separator + "conf" + File.separator + "apiFiles" + File.separator + apiFile.fileName();
                            File apiXmlFile = new File(apiXmlFileName);

                            // 通过read方法读取一个文件 转换成Document对象
                            Document document = reader.read(apiXmlFile);
                            //获取根节点元素对象
                            Element root = document.getRootElement();
                            List<Element> apiNodes = root.elements("api");

                            apiNodes.forEach((apiNode) -> {
                                String methodName = apiNode.element("methodName").getTextTrim();

                                TAppMethod appMethod = new TAppMethod()
                                        .setMethodName(methodName)
                                        .setCallFlag(1)
                                        .setUrl(methodUrl)
                                        .setMethodId(action.actionid())
                                        .setAuth(action.auth())
                                        .setResult(finalMethodResult)
                                        .setSort(Integer.parseInt(apiNode.element("sort").getTextTrim()))
                                        .setSupportMethods(String.join("/", action.methods()));
                                module.addMethod(appMethod);

                                //业务脚本
                                TAppMethodParam businessMethodParam = new TAppMethodParam()
                                        .setParamName("businessMethod")
                                        .setParamComment("业务名称")
                                        .setParamRequired(true)
                                        .setParamSrc(apiNode.elementTextTrim("businessMethod"))
                                        .setParamType("String");
                                appMethod.addParam(businessMethodParam);

                                //token参数
                                String tokenFrom = apiNode.elementTextTrim("tokenFrom");
                                if (StringUtils.isNotBlank(tokenFrom)) {
                                    TAppMethodParam tokenParam = new TAppMethodParam()
                                            .setParamName("token")
                                            .setParamComment("操作token")
                                            .setParamRequired(true)
                                            .setParamSrc(tokenFrom)
                                            .setParamType("String");
                                    appMethod.addParam(tokenParam);
                                }

                                String pageFrom = apiNode.elementTextTrim("pageFrom");
                                if (StringUtils.isNotBlank(pageFrom)) {
                                    TAppMethodParam pageParam = new TAppMethodParam()
                                            .setParamName("page")
                                            .setParamComment("分页参数")
                                            .setParamRequired(true)
                                            .setParamSrc("{\"pageIndex\": x, \"pageSize\": y }")
                                            .setParamType("PageFlipper");
                                    appMethod.addParam(pageParam);
                                }

                                TAppMethodParam invokeParam = new TAppMethodParam()
                                        .setParamName("params")
                                        .setParamComment("JSON序列化参数")
                                        .setParamRequired(true)
                                        .setParamSrc("参数见下表")
                                        .setParamType("String");
                                appMethod.addParam(invokeParam);

                                String paramOnly = apiNode.elementTextTrim("paramOnly");
                                if (StringUtils.isNotBlank(paramOnly)) {
                                    try {
                                        //在对象里面找注解的字段
                                        Class<?> ptype = Class.forName(paramOnly);
                                        generateCallParam("", ptype, apiNode.elementTextTrim("businessMethod"), appMethod);

                                    } catch (ClassNotFoundException e) {
                                        throw new RuntimeException(e);
                                    }
                                } else {
                                    Element paramsNode = apiNode.element("params");
                                    List<Element> paramNodeList = paramsNode.elements("param");
                                    paramNodeList.forEach((callParamNode) -> {
                                        String callParamType = callParamNode.elementTextTrim("paramKind");
                                        if (Arrays.stream(simpleParamType).noneMatch((x) -> x.equalsIgnoreCase(callParamType))) {
                                            //对象
                                            //基础类型
                                            TAppCallParam callParam = null;
                                            try {
                                                callParam = new TAppCallParam()
                                                        .setParamName(callParamNode.elementTextTrim("paramKey"))
                                                        .setParamComment(callParamNode.elementTextTrim("paramComment"))
                                                        .setParamRequired(true)
                                                        .setParamSrc(Class.forName(callParamType).getSimpleName())
                                                        .setParamType(callParamType);
                                                appMethod.addCallParam(callParam);

                                                //在对象里面找注解的字段
                                                Class<?> ptype = Class.forName(callParamType);
                                                generateCallParam("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", ptype, apiNode.elementTextTrim("businessMethod"), appMethod);
                                            } catch (ClassNotFoundException e) {
                                                throw new RuntimeException(e);
                                            }

                                        } else {
                                            //基础类型
                                            TAppCallParam callParam = new TAppCallParam()
                                                    .setParamName(callParamNode.elementTextTrim("paramKey"))
                                                    .setParamComment(callParamNode.elementTextTrim("paramComment"))
                                                    .setParamRequired(true)
                                                    .setParamSrc("")
                                                    .setParamType(callParamType);

                                            appMethod.addCallParam(callParam);
                                        }
                                    });
                                }

                                List<Element> apiBeanNodeList = apiNode.elements("webApiBean");
                                apiBeanNodeList.forEach((apiBeanNode) -> {
                                    String apiBeanType = apiBeanNode.getTextTrim();
                                    if (StringUtils.isNotBlank(apiBeanType)) {
                                        try {
                                            Class<?> ptype = Class.forName(apiBeanType);

                                            //region 对象表格
                                            List<TAppClassField> fieldList = new LinkedList<>();
                                            for (Field field : ptype.getDeclaredFields()) {
                                                if (Modifier.isFinal(field.getModifiers())) {
                                                    continue;
                                                }
                                                if (Modifier.isStatic(field.getModifiers())) {
                                                    continue;
                                                }

                                                TAppClassField classField = new TAppClassField();
                                                classField.setFieldName(field.getName());
                                                classField.setFieldComment("");
                                                Comment comment = field.getAnnotation(Comment.class);
                                                if (comment != null) {
                                                    classField.setFieldComment(comment.value());
                                                }
                                                classField.setFieldCurrent(0);
                                                ApiPlace[] apiPlaces = field.getAnnotationsByType(ApiPlace.class);
                                                for (ApiPlace place : apiPlaces) {
                                                    classField.getFieldPlace().add(place.value());
                                                    if (apiNode.elementTextTrim("businessMethod").equalsIgnoreCase(place.value())) {
                                                        classField.setFieldCurrent(1);
                                                    }
                                                }

                                                fieldList.add(classField);
                                            }

                                            TAppMethodClass methodClass = new TAppMethodClass()
                                                    .setClassName(ptype.getSimpleName())
                                                    .setClassField(fieldList)
                                                    .setResult(false);

                                            appMethod.addClass(methodClass);
                                            //endregion

                                        } catch (ClassNotFoundException e) {
                                            throw new RuntimeException(e);
                                        }
                                    }


                                });
                                WebApiBean[] apiBeans = method.getAnnotationsByType(WebApiBean.class);
                                for (WebApiBean apiBean : apiBeans) {
                                    final boolean isarray = apiBean.type().isArray();
                                    final Class ptype = isarray ? apiBean.type().getComponentType() : apiBean.type();

                                    if (ptype.isPrimitive() || ptype == String.class || ptype == PageFlipper.class) {
                                        continue;
                                    }

                                    if (!appMethod.containClass(ptype.getSimpleName(), apiBean.result())) {
                                        //region 对象表格
                                        List<TAppClassField> fieldList = new LinkedList<>();
                                        for (Field field : ptype.getDeclaredFields()) {
                                            if (Modifier.isFinal(field.getModifiers())) {
                                                continue;
                                            }
                                            if (Modifier.isStatic(field.getModifiers())) {
                                                continue;
                                            }

                                            TAppClassField classField = new TAppClassField();
                                            classField.setFieldName(field.getName());
                                            classField.setFieldComment("");
                                            Comment comment = field.getAnnotation(Comment.class);
                                            if (comment != null) {
                                                classField.setFieldComment(comment.value());
                                            }
                                            classField.setFieldCurrent(0);
                                            ApiPlace[] apiPlaces = field.getAnnotationsByType(ApiPlace.class);
                                            for (ApiPlace place : apiPlaces) {
                                                classField.getFieldPlace().add(place.value());
                                                if (methodUrl.equalsIgnoreCase(place.value())) {
                                                    classField.setFieldCurrent(1);
                                                }
                                            }

                                            fieldList.add(classField);
                                        }

                                        TAppMethodClass methodClass = new TAppMethodClass()
                                                .setClassName(ptype.getSimpleName())
                                                .setClassField(fieldList)
                                                .setResult(apiBean.result());

                                        appMethod.addClass(methodClass);
                                        //endregion
                                    }
                                }
                            });
                        }
                    } else {
                        String methodUrl = prefix + action.url();
                        Boolean auth = action.auth();
                        Integer actionId = action.actionid();
                        String methodName = "";
                        if (StringUtils.isNotEmpty(action.comment())) {
                            methodName = action.comment();
                        } else {
                            methodName = method.getName();
                        }
                        String methodResult = action.result();
                        methodResult = methodResult.replace("<", " ");
                        methodResult = methodResult.replace(">", " ");

                        TAppMethod appMethod = new TAppMethod()
                                .setMethodName(methodName)
                                .setCallFlag(0)
                                .setUrl(methodUrl)
                                .setMethodId(actionId)
                                .setAuth(auth)
                                .setResult(methodResult)
                                .setSort(action.sort())
                                .setSupportMethods(String.join("/", action.methods()));
                        module.addMethod(appMethod);

                        String jQueryMethod = "post";

                        if (action.methods().length > 0) {
                            String methodArrayStr = String.join("/", action.methods());
                            methodArrayStr = methodArrayStr.toLowerCase();
                            if (methodArrayStr.contains("post")) {
                                jQueryMethod = "post";
                            } else if (methodArrayStr.contains("get")) {
                                jQueryMethod = "get";
                            }
                        }


                        List<String> jsDefineList = new ArrayList<>();
                        List<String> jsReferenceList = new ArrayList<>();

                        for (HttpParam param : method.getAnnotationsByType(HttpParam.class)) {
                            //region 服务说明和参数表格
                            String paramSrc = "";
                            if (param.src() == HttpParamSourceType.COOKIE) {
                                paramSrc = "Cookie";
                            } else if (param.src() == HttpParamSourceType.HEADER) {
                                paramSrc = "Header";
                            } else if (param.src() == HttpParamSourceType.BODY) {
                                paramSrc = "Body";
                            } else if (param.src() == HttpParamSourceType.PARAMETER) {
                                paramSrc = "Parameter";
                            }
                            TAppMethodParam methodParam = new TAppMethodParam()
                                    .setParamName(param.name())
                                    .setParamComment(param.comment())
                                    .setParamRequired(param.required())
                                    .setParamSrc(paramSrc)
                                    .setParamType(param.type().getSimpleName());

                            appMethod.addParam(methodParam);
                            //endregion

                            //参数类型
                            final boolean isarray = param.type().isArray();
                            final Class<?> ptype = isarray ? param.type().getComponentType() : param.type();

                            //region 示例代码
                            if ("parameter".equalsIgnoreCase(paramSrc)) {
                                if (!"&".equalsIgnoreCase(param.name())) {
                                    if (ClassesUtils.isPrimitive(ptype)) {
                                        Class<?> primitiveClass = ClassesUtils.getPrimitive(ptype);
                                        if (primitiveClass != null) {
                                            if (primitiveClass == int.class) {
                                                jsDefineList.add("var " + param.name() + " = 测试整数;");
                                                jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": " + param.name() + ",");
                                            } else if (primitiveClass == long.class) {
                                                jsDefineList.add("var " + param.name() + " = '测试长整数';");
                                                jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": " + param.name() + ",");
                                            } else if (primitiveClass == short.class) {
                                                jsDefineList.add("var " + param.name() + " = '测试整数';");
                                                jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": " + param.name() + ",");
                                            } else if (primitiveClass == boolean.class) {
                                                jsDefineList.add("var " + param.name() + " = 测试bool参数;");
                                                jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": " + param.name() + ",");
                                            } else if (primitiveClass == byte.class) {
                                                jsDefineList.add("var " + param.name() + " = 测试字节数组;");
                                                jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": " + param.name() + ",");
                                            } else if (primitiveClass == float.class) {
                                                jsDefineList.add("var " + param.name() + " = 测试浮点float参数;");
                                                jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": " + param.name() + ",");
                                            } else if (primitiveClass == double.class) {
                                                jsDefineList.add("var " + param.name() + " = 测试浮点double参数;");
                                                jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": " + param.name() + ",");
                                            }
                                        }
                                    } else if (ptype == String.class) {
                                        jsDefineList.add("var " + param.name() + " = '测试字符串';");
                                        jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": " + param.name() + ",");
                                    } else if (ptype == PageFlipper.class) {
                                        jsDefineList.add("var " + param.name() + " = {");
                                        jsDefineList.add(SPACE8 + "pageIndex: 页码(整数),");
                                        jsDefineList.add(SPACE8 + "pageSize: 每页记录数(整数),");
                                        jsDefineList.add("};");
                                        jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": JSON.stringify(" + param.name() + "),");
                                    } else {
                                        jsDefineList.add("var " + param.name() + " = {;");
                                        for (Field field : ptype.getDeclaredFields()) {
                                            if (Modifier.isFinal(field.getModifiers())) {
                                                continue;
                                            }
                                            if (Modifier.isStatic(field.getModifiers())) {
                                                continue;
                                            }

                                            String fieldcomment = "";
                                            Comment comment = field.getAnnotation(Comment.class);
                                            if (comment != null) {
                                                fieldcomment = comment.value();
                                            }
                                            ApiPlace[] apiPlaces = field.getAnnotationsByType(ApiPlace.class);
                                            for (ApiPlace place : apiPlaces) {
                                                if (methodUrl.equalsIgnoreCase(place.value())) {
                                                    jsDefineList.add(SPACE8 + field.getName() + ": " + fieldcomment + ",");
                                                }
                                            }
                                        }
                                        jsDefineList.add("};");

                                        jsReferenceList.add(SPACE16 + "\"" + param.name() + "\": JSON.stringify(" + param.name() + "),");
                                    }

                                }
                            }
                            //endregion

                            if (ptype.isPrimitive() || ptype == String.class || ptype == PageFlipper.class) {
                                continue;
                            }

                            //region 对象表格
                            List<TAppClassField> fieldList = new LinkedList<>();
                            for (Field field : ptype.getDeclaredFields()) {
                                if (Modifier.isFinal(field.getModifiers())) {
                                    continue;
                                }
                                if (Modifier.isStatic(field.getModifiers())) {
                                    continue;
                                }

                                TAppClassField classField = new TAppClassField();
                                classField.setFieldName(field.getName());
                                classField.setFieldComment("");
                                Comment comment = field.getAnnotation(Comment.class);
                                if (comment != null) {
                                    classField.setFieldComment(comment.value());
                                }
                                classField.setFieldCurrent(0);
                                ApiPlace[] apiPlaces = field.getAnnotationsByType(ApiPlace.class);
                                for (ApiPlace place : apiPlaces) {
                                    classField.getFieldPlace().add(place.value());
                                    if (methodUrl.equalsIgnoreCase(place.value())) {
                                        classField.setFieldCurrent(1);
                                    }
                                }

                                fieldList.add(classField);
                            }

                            TAppMethodClass methodClass = new TAppMethodClass()
                                    .setClassName(param.type().getSimpleName())
                                    .setClassField(fieldList)
                                    .setResult(false);

                            appMethod.addClass(methodClass);
                            //endregion
                        }

                        appMethod.getDemoJquery().addAll(jsDefineList);
                        appMethod.getDemoJquery().add("");
                        appMethod.getDemoJquery().add("$.ajax({");
                        appMethod.getDemoJquery().add(SPACE8 + "url: '/apis" + methodUrl + "',");
                        appMethod.getDemoJquery().add(SPACE8 + "type: '" + jQueryMethod + "',");
                        appMethod.getDemoJquery().add(SPACE8 + "data: {");
                        appMethod.getDemoJquery().addAll(jsReferenceList);
                        //appMethod.getDemoJquery().add(SPACE16 + "\"user\": JSON.stringify(data)");
                        appMethod.getDemoJquery().add(SPACE8 + "},");
                        appMethod.getDemoJquery().add(SPACE8 + "dataType: 'json',");
                        appMethod.getDemoJquery().add(SPACE8 + "contentType: 'application/json',");
                        appMethod.getDemoJquery().add(SPACE8 + "success: function (res) {");
                        appMethod.getDemoJquery().add(SPACE16 + "if(res.httpCode == 200){");
                        appMethod.getDemoJquery().add(SPACE24 + "console.log(res);");
                        appMethod.getDemoJquery().add(SPACE16 + "} else {");
                        appMethod.getDemoJquery().add(SPACE24 + "alert(res.msg);");
                        appMethod.getDemoJquery().add(SPACE16 + "}");
                        appMethod.getDemoJquery().add(SPACE8 + "},");
                        appMethod.getDemoJquery().add(SPACE8 + "error: function (res) {");
                        appMethod.getDemoJquery().add(SPACE16 + "alert(res);");
                        appMethod.getDemoJquery().add(SPACE8 + "}");
                        appMethod.getDemoJquery().add("});");

                        WebApiBean[] apiBeans = method.getAnnotationsByType(WebApiBean.class);
                        for (WebApiBean apiBean : apiBeans) {
                            final boolean isarray = apiBean.type().isArray();
                            final Class ptype = isarray ? apiBean.type().getComponentType() : apiBean.type();

                            if (ptype.isPrimitive() || ptype == String.class || ptype == PageFlipper.class) {
                                continue;
                            }

                            if (!appMethod.containClass(ptype.getSimpleName(), apiBean.result())) {
                                //region 对象表格
                                List<TAppClassField> fieldList = new LinkedList<>();
                                for (Field field : ptype.getDeclaredFields()) {
                                    if (Modifier.isFinal(field.getModifiers())) {
                                        continue;
                                    }
                                    if (Modifier.isStatic(field.getModifiers())) {
                                        continue;
                                    }

                                    TAppClassField classField = new TAppClassField();
                                    classField.setFieldName(field.getName());
                                    classField.setFieldComment("");
                                    Comment comment = field.getAnnotation(Comment.class);
                                    if (comment != null) {
                                        classField.setFieldComment(comment.value());
                                    }
                                    classField.setFieldCurrent(0);
                                    ApiPlace[] apiPlaces = field.getAnnotationsByType(ApiPlace.class);
                                    for (ApiPlace place : apiPlaces) {
                                        classField.getFieldPlace().add(place.value());
                                        if (methodUrl.equalsIgnoreCase(place.value())) {
                                            classField.setFieldCurrent(1);
                                        }
                                    }

                                    fieldList.add(classField);
                                }

                                TAppMethodClass methodClass = new TAppMethodClass()
                                        .setClassName(ptype.getSimpleName())
                                        .setClassField(fieldList)
                                        .setResult(apiBean.result());

                                appMethod.addClass(methodClass);
                                //endregion
                            }
                        }
                    }

                }

                module.getMethodList().sort((x, y) -> {
                    if (x.getSort() == y.getSort()) {
                        return StringUtils.compare(x.getMethodName(), y.getMethodName());
                    } else {
                        return Integer.compare(x.getSort(), y.getSort());
                    }
                });
            }
        }

        moduleList.sort((x, y) -> StringUtils.compare(x.getModuleName(), y.getModuleName()));
    }

    public List<TAppModule> getModuleList() {
        return moduleList;
    }
}
