# -*- coding:utf-8 -*-
# Author: Liaojiang

"""
python AI推演开始模块, 在此模块中启动
请修改适用自己的配置后，勿上传
"""

import time
import logging
import os
import multiprocessing as mp

from agent.config import LingYiConfig
from engine.LingYi.entitys.deduce_RL import Deduction


def main(config, process_index):
    """
    启动运行函数
    :param config:  dict, 环境和智能体配置
    :param process_index:  int, 进程序号
    :return: str, game result
    """
    # 设置Log日志
    pro_log = logging.getLogger("Platform%d" % process_index)
    pro_log.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)
    # pro_log.propagate = False
    pro_log.addHandler(console)

    # 创建日志目录
    crt_dir = os.getcwd()
    logs_path = os.path.join(crt_dir, "logs")
    if not os.path.exists(logs_path):
        os.mkdir(logs_path)

    # 设置日志输出到文件
    file_out = logging.FileHandler(r"./logs/simulate_p%d.log" % process_index, mode='w', delay=False)
    file_out.setLevel(logging.INFO)
    file_out.setFormatter(formatter_play)
    pro_log.addHandler(file_out)
    config["game_server"]["logger"] = pro_log
    # 推演运行
    lingyi_env = Deduction(config)
    episodes = 1
    if "episodes" in config["game_server"]["simulate"]:
        episodes = config["game_server"]["simulate"]["episodes"]
    train_episode = 1
    while True:
        reset_result = 0
        for i in range(3):
            # 尝试3此
            reset_result = lingyi_env.reset(train_episode)
            if reset_result == 1:
                # 1：成功， 0:管理服务连接出错， -1: 推演服务连接失败,-2:后台无推演想定，-3：没有获取后台初始态势
                break
            time.sleep(3)
        if reset_result != 1:
            # 连接后台问题或无想定问题，终止运行智能体
            print("连接后台或想定出错，标志:%d, 退出运行智能体！" % reset_result)
            break
        while True:
            lingyi_env.step({})  # 智能体决策和步进推演
            if lingyi_env.is_done():
                # 推演结束或训练时智能体判断结束本局，或推演后台崩溃等问题
                break
        train_episode += 1
        if train_episode > episodes:
            # 已到设定的推演局数，终止
            break

    input("进程%d推演结束，请按任意键退出...\n" % process_index)


if __name__ == '__main__':
    config = LingYiConfig.get_server_config({})
    config.update(LingYiConfig.get_rule_config({}))
    process_count = 4
    if "process_count" in config["game_server"]["simulate"]:
        process_count = config["game_server"]["simulate"]["process_count"]

    if process_count == 1:
        main(config, 1)
    else:
        p_list = []
        for p_index in range(1, process_count+1):
            room_name = "room_t%d" % p_index
            # 第一个进程清除所有房间
            if p_index == 1:
                config["game_server"]["simulate"]["clear_room"] = True
            else:
                config["game_server"]["simulate"]["clear_room"] = False
            config["game_server"]["server"]["room_name"] = room_name
            config["game_server"]["simulate"]["process_id"] = p_index
            p = mp.Process(target=main, args=(config, p_index, ))
            p.start()
            if p_index == 1:
                time.sleep(2)  # 让第一个进行先运行，清空房间完成
            p_list.append(p)
        for p in p_list:
            p.join()

