# -*- encoding=utf8 -*-
import os
import sys
import json
import ast
import yaml
curPath = os.path.abspath(os.path.dirname(__file__))
data_path = curPath + os.sep + "data"


class parseCode(object):

    def getYamlValue(self, filename):
        """
        获取公共sql中的sql
        :param filename:
        :return:
        """
        f = open(filename, 'r', encoding='utf-8')
        cont = f.read()
        value = yaml.load(cont, Loader=yaml.Loader)
        f.close()
        return value

    def scan_java_doc(self, path, class_name):
        flag = True
        controllers = []
        for controller_file in os.listdir(path):
            controllers.append(controller_file)
        expect_file = ("".join(class_name[:1].upper() + class_name[1:]).replace("\n", "") + ".java").\
            replace("(object)", "").replace(" ", "")
        filename = path + os.sep + expect_file
        if expect_file in controllers:
            # 读取文件在后面追加方法
            flag = False
        return flag, filename, expect_file

    def scan_java_code(self, filename, file_hash):
        root_path = ""
        entity_path = ""
        entity_name = ""
        path_flag = False
        entity_flag = False
        paramsKeys = []
        params = {}
        f = open(filename, "r", encoding="utf-8")
        lines = f.readlines()
        if "entity_name" in file_hash:
            entity_flag = True
            entity_name = file_hash["entity_name"]
        for line in lines:
            if "@RequestMapping" in line and "value" not in line:
                root_path = line.split("\"")[1].split("\"")[0]
            elif "@RequestMapping" in line and "value" in line:
                path = line.split("\"")[1].split("\"")[0]
                all_path = root_path + path
                if all_path == file_hash["path"]:
                    path_flag = True
            elif path_flag and "@RequestBody" in line:
                boby = line.split("@RequestBody")[1].split(" ")[1].replace(" ", "")
                if file_hash["entity_name"] == boby:
                    file_hash["other_params"] = {}
                    entity_new_path = entity_path.rsplit("/", 1)[0] + "/" + boby + ".java"
                    f = open(entity_new_path, "r", encoding="utf-8")
                    model_lines = f.readlines()
                    for model_line in model_lines:
                        if "private" in model_line:
                            params_key = model_line.split(" ")[2].replace(";", "").replace("\n", "")
                            params_val = model_line.split(" ")[1]
                            paramsKeys.append(params_key)
                            params[params_key] = params_val
                    for key, val in file_hash["params"].items():
                        if key not in paramsKeys:
                            file_hash["other_params"][key] = val
                        else:
                            if self.typeof(file_hash["params"][key]) != params[key]:
                                file_hash["other_params"][key] = val
                    if len(file_hash["other_params"]) > 0:
                        new_f = open(entity_new_path, 'r', encoding="utf-8")
                        lines = new_f.readlines()
                        new = []
                        for line in lines:
                            if "private" in line:
                                params_key = line.split(" ")[2].replace(";", "").replace("\n", "")
                                if params_key not in file_hash["other_params"]:
                                    new.append(line)
                            elif line.replace("\n", "").replace(" ", "") == "}":
                                pass
                            else:
                                for k, v in file_hash["other_params"].items():
                                    if k not in line:
                                        new.append(line)
                        with open(entity_new_path, "w") as filewrite:
                            for var in new:
                                filewrite.write(var)
                            for k, v in file_hash["other_params"].items():
                                self.get_set_entity(filewrite, k, v)
                            filewrite.write("}")
            elif entity_flag and "."+entity_name+";" in line:
                entity_package = line.replace("import", "").replace(";", "").replace(" ", "")
                entity_path = str(file_hash["root_path"]).split(entity_package.split(".")[0])[0] + entity_package.replace(".", "/")

    def get_set_entity(self, model_file, key, val):
        if isinstance(val, str):
            model_file.write("private String " + key + ";\n")
            key_d = "".join(key[:1].upper() + key[1:])
            model_file.write("public1 String get" + key_d + "() { return " + key
                             + ";}\n")
            model_file.write("public1 void set" + key_d + "(String " + key +
                             ") { this." + key + " = " + key + ";}\n")
        elif isinstance(val, list):
            model_file.write("private List<Object> " + key + ";\n")
            key_d = "".join(key[:1].upper() + key[1:])
            model_file.write("public1 List<Object> get" + key_d + "() { return " + key
                             + ";}\n")
            model_file.write("public1 void set" + key_d + "(List<Object> " + key +
                             ") { this." + key + " = " + key + ";}\n")
        elif isinstance(val, int):
            model_file.write("private int " + key + ";\n")
            key_d = "".join(key[:1].upper() + key[1:])
            model_file.write("public1 int get" + key_d + "() { return " + key
                             + ";}\n")
            model_file.write("public1 void set" + key_d + "(int " + key +
                             ") { this." + key + " = " + key + ";}\n")

    def param_set(self, key, val, result):
        if isinstance(val, str):
            result = result + "@RequestParam String " + key + ","
        elif isinstance(val, list):
            result = result + "@RequestParam List<Object> " + key + ","
        elif isinstance(val, int):
            result = result + "@RequestParam int " + key + ","
        return result

    def typeof(self, variate):
        """
        变量类型
        :param variate:
        :return:
        """
        if isinstance(variate, int):
            return "int"
        elif isinstance(variate, str):
            return "String"
        elif isinstance(variate, float):
            return "float"
        elif isinstance(variate, list):
            return "list"
        elif isinstance(variate, tuple):
            return "tuple"
        elif isinstance(variate, dict):
            return "dict"
        elif isinstance(variate, set):
            return "set"
        else:
            return None


    def scan_auto_code(self, path, javaAddress):
        file_hash = {}
        dirs = os.listdir(path)
        for dir in dirs:
            if dir == "air_case":
                air_paths = os.listdir(path + os.sep + dir)
                for air_path in air_paths:
                    if air_path != '.DS_Store':
                        path = curPath + os.sep + dir + os.sep + air_path
                        case_paths = os.listdir(path)
                        for case_path in case_paths:
                            filename = path + os.sep + case_path + os.sep + case_path.replace(".air", ".py")
                            modulename = filename.split("air_case/")[1].split("/")[0]
                            rootpath = filename.split("air_case/")[0]
                            yaml_path = rootpath + "data" + os.sep + modulename + os.sep + "data"
                            if os.path.exists(yaml_path):
                                yaml_result = self.getYamlValue(yaml_path)
                            # 读取需要同步的接口代码
                            f = open(filename, "r", encoding="utf-8")
                            lines = f.readlines()
                            class_flag = False
                            flag_isRun = False
                            flag_newOrOld = False
                            for line in lines:
                                if "case_tag" in line and "change_java_code" in line:
                                    flag_isRun = True
                                elif "class" in line and flag_isRun:
                                    class_name = line.replace(":", "").replace("class", "").replace(" ", "")
                                    flag_newOrOld, filename, expectFile = self.scan_java_doc(javaAddress, class_name)
                                    class_flag = True
                                    file_hash["className"] = expectFile
                                    file_hash["root_path"] = filename.split("/controller")[0]
                                    file_hash["package"] = "com" + filename.split("/controller")[0].split("/com")[1].replace("/", ".")
                                elif "def" in line and class_flag and flag_isRun:
                                    method = line.split("(")[0].replace("def", "").replace(" ", "")
                                    file_hash["method"] = method
                                elif ("payload_" in line and "commonFuc().get_business_data" in line) and class_flag and flag_isRun:
                                    if "RequestParam" in line:
                                        file_hash["param_type"] = "RequestParam"
                                    elif "payload_" in line:
                                        file_hash["param_type"] = "Entity"
                                        file_hash["entity_name"] = line.split("=")[0].replace("payload_", "").replace(" ", "")
                                    param_data = line.split("\"")[1].split("\"")[0]
                                    file_hash["params"] = yaml_result[param_data]
                                elif "_url" in line and class_flag and flag_isRun:
                                    url_data = line.split("+")[1].split("\"")[1].split("\"")[0]
                                    file_hash["path"] = yaml_result[url_data]
                                elif "commonFuc().http_" in line and class_flag and flag_isRun:
                                    post_get = line.split("http_")[1].split("(")[0]
                                    file_hash["methodPath"] = "@RequestMapping(value = \"" + file_hash["path"] + "\", method = RequestMethod." + post_get.upper() + ")"
                                elif "checkDict_" in line and "check_result" not in line and flag_isRun:
                                    file_hash["response"] = line.split("=")[0].replace("checkDict_", "").replace(" ", "")
                            if flag_isRun:
                                if flag_newOrOld:
                                    file = open(filename, 'w')
                                    file.write("package " + file_hash["package"] + ".controller;\n\n\n")
                                    file.write("@RestController\n")
                                    file.write("public1 class " + file_hash["className"].replace(".java", "") + " {" + "\n")
                                    file.write("\n\n")
                                    file.write(file_hash["methodPath"])
                                    file.write("\n@ResponseBody \n")
                                    if "params" in file_hash:
                                        if file_hash["param_type"] == "RequestParam":
                                            param_body = ""
                                            for key, val in file_hash["params"].items():
                                                param_body = self.param_set(key, val, param_body)
                                            file.write("public1 " + file_hash["response"] + " " + file_hash["method"] + "(" + param_body[:-1] + ") {\n")
                                        else:
                                            entity_name = file_hash["entity_name"]
                                            param_body = "@RequestBody " + entity_name + " " + str.lower(entity_name)
                                            file.write("public1 " + file_hash["response"] + " " + file_hash["method"] + "("
                                                       + param_body + ") {\n")
                                            model_path = file_hash["root_path"] + "/model"
                                            if not os.path.exists(model_path):
                                                os.mkdir(model_path)
                                            model_filename = model_path + os.sep + entity_name + ".java"
                                            if os.path.exists(model_filename):
                                                os.remove(model_filename)
                                            model_file = open(model_filename, 'a')
                                            model_file.write("package " + file_hash["package"] + ".model;\n\n\n")
                                            model_file.write("public1 class " + entity_name + "{\n\n")
                                            for key, val in file_hash["params"].items():
                                                self.get_set_entity(model_file, key, val)
                                            model_file.write("}\n")
                                    file.write("\n return null; \n")
                                    file.write(" }\n")
                                    file.write("}\n")
                                else:
                                    self.scan_java_code(filename, file_hash)


if __name__ == '__main__':
    # 第一个参数 本地java代码地址
    #pool = sys.argv[1]
    f = open(curPath + os.sep + 'javaAddressPath.txt', "r", encoding="utf-8")
    lines = f.readlines()
    javaAddress = lines[0].replace("\n", "").replace(" ", "")
    parseCode().scan_auto_code(curPath, javaAddress)


