import subprocess, os, time, shutil, configparser, sys

# 获取当前文件的父目录的绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 获取父目录的绝对路径
parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
# 将父目录添加到 Python 模块搜索路径中
sys.path.append(parent_dir)

from Utils import utils as globalUtils

# python.exe main.py E:\01-Projects\01-CAE-FullLink\output\workingDir\test06\SurfaceCharacteristicSimulation

inputDir = "input/"
inputDistDir = "Dir_REF/"
outputSourceDir = "Dir_REF/"
outputDistDir = "output/"


def readParamValueList(paramFilePath: str):
    paramValueList = []
    with open(paramFilePath, "r", encoding="utf-8") as file:
        for line in file:
            paramValueList = paramValueList + [float(x) for x in line.split(",")]
    return paramValueList


# 读取输入文件,生成所有组合的值
def readInput() -> list:
    # 读取input_surface.txt,获取每个参数文件公共内容部分
    inputfilePath = inputDir + "input_surface.txt"
    paramNameList = ""
    publicParamValueList = []
    with open(inputfilePath, "r", encoding="utf-8") as file:
        lines = file.readlines()
        paramNameList = lines[0]
        publicParamValueList = [int(x) for x in lines[1].split(",")]
    print(paramNameList)
    print(publicParamValueList)

    # 依次读取 Lat、Lon、SA、SZ、VA、VZ
    latFilePath = inputDir + "Lat.txt"
    latValueList = readParamValueList(latFilePath)

    lonFilePath = inputDir + "Lon.txt"
    lonValueList = readParamValueList(lonFilePath)

    saFilePath = inputDir + "SA.txt"
    saValueList = readParamValueList(saFilePath)

    szFilePath = inputDir + "SZ.txt"
    szValueList = readParamValueList(szFilePath)

    vaFilePath = inputDir + "VA.txt"
    vaValueList = readParamValueList(vaFilePath)

    vzFilePath = inputDir + "VZ.txt"
    vzValueList = readParamValueList(vzFilePath)

    print("经度参数个数 " + str(len(latValueList)))
    print("纬度参数个数 " + str(len(lonValueList)))
    print("太阳天顶角参数个数 " + str(len(saValueList)))
    print("观察天顶角参数个数 " + str(len(szValueList)))
    print("太阳方位角参数个数 " + str(len(vaValueList)))
    print("观测方位角参数个数 " + str(len(vzValueList)))

    if not globalUtils.are_equal(
        len(latValueList),
        len(lonValueList),
        len(saValueList),
        len(szValueList),
        len(vaValueList),
        len(vzValueList),
    ):
        print(
            "经度、纬度、太阳天顶角、观察天顶角、太阳方位角、观测方位角的参数个数不一致,请查看参数文件。"
        )
        return []

    # 参数内容列表
    paramContentList = []
    for index, lat in enumerate(latValueList):
        lon = lonValueList[index]
        sa = saValueList[index]
        sz = szValueList[index]
        va = vaValueList[index]
        vz = vzValueList[index]
        paramContentList.append(
            [
                publicParamValueList[0],
                lon,
                lat,
                sz,
                vz,
                sa,
                va,
                publicParamValueList[1],
                publicParamValueList[2],
            ]
        )
    # print(latValueList)
    # return [paramNameList, paramValueList.split(",")]
    return [paramNameList, paramContentList]


# 从项目目录下拷贝参数文件过来
def copyInputFiles(projectDir: str) -> bool:

    # 先删除,再创建
    globalUtils.rmPath(inputDir)
    os.mkdir(inputDir)
    inputFileList = [
        "input_surface.txt",
        "Lat.txt",
        "Lon.txt",
        "SA.txt",
        "SZ.txt",
        "VA.txt",
        "VZ.txt",
    ]

    for inputFile in inputFileList:
        inputFileProjectPath = os.path.join(projectDir, inputFile)
        if not os.path.isfile(inputFileProjectPath):
            print(f"{inputFileProjectPath} is not file or exist")
            return False
        inputFileSolverPath = os.path.join(inputDir, inputFile)
        shutil.copy(inputFileProjectPath, inputFileSolverPath)

    return True


# 执行一次求解
def executeCompute(
    inputFile: str, paramNameList, paramContent, outputSourceFile, outputDistFile
):
    # 先删除旧的input.txt
    globalUtils.rmPath(inputFile)
    # 生成新的input.txt
    with open(inputFile, "w") as file:
        file.write(paramNameList)
        file.write(paramContent)

    # 先删除旧的output.txt
    globalUtils.rmPath(outputSourceFile)
    # 启动求解任务
    result = subprocess.run(["Cal_REF/Cal_REF.exe", "Dir_REF/input.txt"], cwd="Cal_REF")

    # 循环等待结果文件的生成,然后进行移动
    while 1:
        time.sleep(3)
        # 如果文件生成,且没有被其他程序打开(被其他程序访问,例如:正在往里写文件)
        if os.path.isfile(outputSourceFile) and not globalUtils.isFileOpen(
            outputSourceFile
        ):
            os.rename(outputSourceFile, outputDistFile)
            break

    return result


# 其它模块调用本模块的求解(大气模块调用)
def toaRunModel(surFileDir: str):
    # 提供的目录下有 input.txt,没有output.txt
    inputSourceFile = os.path.join(surFileDir, "input.txt")
    outputDistFile = os.path.join(surFileDir, "output.txt")

    # 求解时的 input.txt和output.txt
    inputFilePath = os.path.join(inputDistDir, "input.txt")
    outputSourceFile = os.path.join(inputDistDir, "output.txt")
    # 第1步,拷贝inputFile到
    with open(inputSourceFile, "r", encoding="utf-8") as file:
        lines = file.readlines()

    if len(lines) < 2:
        return None
    return executeCompute(
        inputFilePath, lines[0], lines[1], outputSourceFile, outputDistFile
    )


def test(testDir: str):
    currentExeDir = os.getcwd()
    print("execute dir: ", currentExeDir)

    # 获取当前文件的绝对路径
    currentFile = os.path.realpath(__file__)

    # 获取当前文件的目录
    currentDir = os.path.dirname(currentFile)

    # 切换到'/home' 目录
    os.chdir(currentDir)
    print("surface dir: ", currentDir)
    inputFilePath = os.path.join(inputDistDir, "input.txt")
    print("surface input.txt: ", inputFilePath)
    print(os.getcwd())

    # 执行一次求解
    result = toaRunModel(testDir)
    print("surface run ok:", result)
    # 切换回之前的目录
    os.chdir(currentExeDir)

    pass


def generateImgPng():
    imgFileDir = "postProcessing"
    pngFileDir = "output"
    caseList = ["Case1", "Case2"]
    for case in caseList:
        imgList = ["07.REF.img", "08.REF.img", "09.REF.img", "10.REF.img"]
        for imgFile in imgList:
            imgFilePath = os.path.join(imgFileDir, case + "/reflectance/" + imgFile)
            pngFilePath = os.path.join(
                pngFileDir, case + "-" + imgFile.replace(".img", ".png")
            )
            pngFilePath = globalUtils.saveENVIImgToPng(imgFilePath, pngFilePath)
        pass


def main():
    # 项目目录的output,求解结束后传回到项目目录下
    projectDir = sys.argv[1]
    print(projectDir)

    # 从项目目录下拷贝参数文件过来
    if not copyInputFiles(projectDir):
        print("参数文件不完整")
        return

    # 读取参数文件
    paramContentValue = readInput()
    if len(paramContentValue) == 0:
        return
    paramNameList = paramContentValue[0]
    paramContentList = paramContentValue[1]

    # 读取配置文件
    # 创建 ConfigParser 对象
    config = configparser.ConfigParser()
    config.read("config.ini")
    taskNum = int(config.get("settings", "taskNum"))

    # 生成的结果文件
    outputSourceFile = outputSourceDir + "output.txt"
    inputFile = inputDistDir + "input.txt"

    # 删除之前的输出文件目录,创建新的目录
    globalUtils.rmPath(outputDistDir)
    os.mkdir(outputDistDir)

    # 获取当前时间戳
    timestamp = time.time()

    # 根据任务数进行求解
    for index, paramContent in enumerate(paramContentList):
        # 只计算200个
        if index == taskNum:
            break

        result = executeCompute(
            inputFile,
            paramNameList,
            ",".join(map(str, paramContent)),
            outputSourceFile,
            outputDistDir + "output" + str(index) + ".txt",
        )

        runTimestamp = time.time()
        print(result, index, runTimestamp - timestamp)
        timestamp = runTimestamp

    # 生成后处理图片
    generateImgPng()

    # 项目目录下的output目录
    projectOutputDir = os.path.join(projectDir, "output")
    # 删除项目目录下旧的结果文件
    globalUtils.rmPath(projectOutputDir)
    # 将结果拷贝到目的目录
    shutil.copytree(outputDistDir, projectOutputDir)

    pass


# 主函数
if __name__ == "__main__":
    try:
        # 尝试执行的代码块
        main()
    except Exception as e:
        # 捕获除了ZeroDivisionError外的所有异常
        print("发生异常:", str(e))
    finally:
        # 无论是否发生异常,最终都会执行该代码块
        print("求解执行完毕!")