# -*- coding:utf-8 -*-
"""
python AI推演开始模块, 在此模块中启动
请修改适用自己的配置后，勿上传
"""
import os
import os.path
import sys
import time
import logging
import traceback

from engine.LingYi.entitys.deduce_RL import Deduction
import engine.LingYi.entitys.commonfunction as commonfun

logger = logging.getLogger("Platform")
logger.setLevel(level=logging.INFO)
formatter_play = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt="%Y-%m-%d %H:%M:%S")
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter_play)
logger.propagate = False
logger.addHandler(console)


def config_agent_entity(config):
    import importlib

    path = config["player"]["agent_path"]
    import_path = config["player"]["agent_import_path"]
    pl_class_name = config["player"]["agent_class_name"]
    print(import_path)

    sys.path.append(path)
    # print(sys.path)

    pl_mode = importlib.import_module(import_path)
    agent_class = getattr(pl_mode, pl_class_name)

    # config["agents"] = {  # 智能体配置
    #     "红方": [  # agent列表. 如果agent类有多个，每一局可随机选择一个agent训练
    #         ["redExample", agent_class, None],  # agent名，类, 以及参数（可选）
    #     ],
    #     "蓝方": [  # 如果agent类有多个，每一局可随机选择一个agent训练
    #         ["blueExample", agent_class, None],  # agent名，类, 以及参数（可选）
    #     ],
    # }
    # 智能体配置
    agent_param = dict()

    agent_param["alg_type"] = 0
    if "alg_type" in config:
        agent_param["alg_type"] = config["alg_type"]
    if "client_select_info" in config:
        agent_param["client_select_info"] = config["client_select_info"]
    if "user_params" in config:
        agent_param["user_params"] = config["user_params"]

    play_side = config["player"]["player_side"]

    # config["agents"] = {
    #     play_side: [
    #         ["redExample", agent_class, agent_param],  # agent名，类, 以及参数（可选）
    #     ]
    # }
    # config["agents"] = {
    #     play_side: [
    #         ["redExample", agent_class, agent_param],  # agent名，类, 以及参数（可选）
    #     ]
    # }
    if hasattr(agent_class, "is_learn"):
        # 是强化学习智能体
        config["RL_agents"] = {
            play_side: {
                "agents": {
                    import_path: {
                        "class": agent_class,
                    }
                }
            }
        }
    else:
        config["rule_config"] = {
            play_side: {
                import_path: {
                    "class": agent_class,
                }
            }
        }
    pass


def get_config_result(config_file, coding='utf-8'):
    """
    获取配置文件中的配置
    :param config_file:  str, 配置文件名
    :param coding:  str, 配置文件编码
    :return:
    """
    config_result = {}
    with open(config_file, mode='r', encoding=coding) as fp:
        lines = fp.readlines()
        for line in lines:
            new_str = line.strip().strip("\ufeff")
            if not new_str.startswith("#") and "=" in new_str:
                e_index = new_str.index("=")
                if e_index > 0:
                    key_data = new_str[0:e_index].strip()
                    value_data = new_str[e_index + 1:].strip()
                    # if "#" in value_data:
                    #     value_data = value_data.split("#")[0].strip()
                    config_result[key_data] = value_data
    return config_result


def parse_simulate_config(simulate_config):
    try:
        if "main_client" in simulate_config:
            simulate_config["main_client"] = (simulate_config["main_client"] == "True")
        if "scenario" in simulate_config:
            simulate_config["scenario"] = str(simulate_config["scenario"])
        if "episodes" in simulate_config:
            simulate_config["episodes"] = int(simulate_config["episodes"])
        if "compression" in simulate_config:
            simulate_config["compression"] = int(simulate_config["compression"])
        if "decision_interval" in simulate_config:
            simulate_config["decision_interval"] = int(simulate_config["decision_interval"])
        if "stop_iters_num" in simulate_config:
            simulate_config["stop_iters_num"] = int(simulate_config["stop_iters_num"])
        if "plan_time" in simulate_config:
            simulate_config["plan_time"] = int(simulate_config["plan_time"])
        if "training" in simulate_config:
            simulate_config["training"] = (simulate_config["training"] == "True")
        if "save_result" in simulate_config:
            simulate_config["save_result"] = (simulate_config["save_result"] == "True")
        return simulate_config
    except Exception as e:
        print(" Err : {}".format(e))


def read_config(config_ini, config_path):
    """
    读取本地文件 config.ini的配置
    :param config_ini:
    :return:
    """

    """框架流程配置文件"""
    server_path = os.path.join(config_path, "config_server.ini")
    # server的配置 以grpc_server 的配置文件为准
    grpc_zl_config_path = os.path.join('grpc_server', 'config', 'config.ini')
    if os.path.exists(grpc_zl_config_path):
        server_path = grpc_zl_config_path

    if os.path.exists(server_path):
        config_ini["server"] = get_config_result(server_path)
    else:
        print("server_path read fail! ", server_path)
        return

    # import_path = os.path.join(config_path, "config_import.ini")
    # if os.path.exists(import_path):
    #     config_ini["import"] = get_config_result(import_path)
    # else:
    #     print("import_path read fail! ", import_path)

    player_path = os.path.join(config_path, "config_player.ini")
    if os.path.exists(player_path):
        config_ini["player"] = get_config_result(player_path)
    else:
        print("player_path read fail! ", player_path)
        return

    simulate_path = os.path.join(config_path, "config_simulate.ini")
    if os.path.exists(simulate_path):
        config_temp = get_config_result(simulate_path)
        config_ini["simulate"] = parse_simulate_config(config_temp)
    else:
        print("simulate_path read fail! ", simulate_path)
        return

    """用户配置文件"""
    client_select_info_path = os.path.join(config_path, "config_client_info.json")
    if os.path.exists(client_select_info_path):
        config_ini["client_select_info"] = commonfun.read_json_file(client_select_info_path)

        user_params_path = os.path.join(config_ini["player"]["agent_path"], "config/alg_info.json")
        if os.path.exists(user_params_path):
            config_temp = commonfun.read_json_file(user_params_path)
            if config_temp is not None:
                if "user_params" in config_temp:
                    config_ini["user_params"] = config_temp["user_params"]
                if "alg_type" in config_temp:
                    config_ini["alg_type"] = int(config_temp["alg_type"])

    """日志记录器"""
    # log_name = "Platform"
    # logfile = os.path.join(os.getcwd(), "log", time.strftime('%Y%m%d%H%M', time.localtime(time.time())) + ".log")
    # if "log_name" in config_ini["simulate"]:
    #     log_name = config_ini["simulate"]["log_name"]
    # if os.path.exists(config_ini["simulate"]["log_path"]):
    #     logfile = os.path.join(config_ini["simulate"]["log_path"], config_ini["server"]["room_name"] + log_name + ".log")
    #
    # # 创建日志记录器，并设置日志记录格式
    # logger = logging.getLogger(log_name)
    # formatter_play = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    #                                    datefmt="%Y-%m-%d %H:%M:%S")
    #
    # # 创建文件处理器，指定日志文件路径和日志级别
    # file_handler = logging.FileHandler(logfile, mode='a', encoding="utf-8")
    # file_handler.setLevel(logging.INFO)
    # file_handler.setFormatter(formatter_play)
    # logger.addHandler(file_handler)

    config_ini["logger"] = logger


def ai_train_config_ini(_config):
    if not ("player" in _config):
        return 0
    if not ("AiTrainTimes" in _config["player"]):
        return 0

    str_ai_times = _config["player"]["AiTrainTimes"]
    ai_times = int(str_ai_times)

    if not isinstance(ai_times, int) or ai_times <= 0:
        return 0

    return ai_times


def main(config_path=" "):
    """
    启动运行函数
    :return: str, game result
    """
    # 加载配置文件
    config = {"is_ai_apply": True}
    try:
        read_config(config, config_path)  # 2025智能体调度
        config_agent_entity(config)  # 2025智能体调度
        deduce_manager = Deduction(config)  # 训练推演管理对象
    except Exception as e:
        if not os.path.exists(os.path.join(config_path, "log")):
            os.makedirs(os.path.join(config_path, "log"))
        file_path = os.path.join(config_path, "log", "command_delay" + ".log")
        file_handler = logging.FileHandler(file_path, mode='a', encoding="utf-8")
        formatter = logging.Formatter('%(asctime)s.%(msecs)03d - %(name)s - %(levelname)s - %(message)s',
                                      datefmt="%Y-%m-%d %H:%M:%S")

        file_handler.setFormatter(formatter)
        # 没有配置日志
        logger = logging.getLogger("Apply")
        logger.setLevel(level=logging.INFO)
        logger.propagate = False
        logger.addHandler(file_handler)
        error_msg = traceback.format_exc()
        logger.error("智能体配置出错:%s" % error_msg)
        raise Exception(e)

    deduce_manager.normal_simulate()  # 正常推演模式
    deduce_manager.logger.info("运行完成，结束")
    time.sleep(1)
    sys.exit(0)


if __name__ == '__main__':
    main()
