# -*- coding: utf-8 -*-
from flask import Flask, render_template,jsonify
from flask_socketio import SocketIO, emit
from scriptBase.comon import *
import pyautogui
import base64
import threading
from dongri_task import *
from collections import deque
import json
from concurrent.futures import ThreadPoolExecutor
from flask_caching import Cache

# 全局线程池，限制最大线程数为1
executor = ThreadPoolExecutor(max_workers=1)

cache = Cache(config={'CACHE_TYPE': 'null'})  # 使用 null 缓存类型
app = Flask(__name__)
cache.init_app(app)
app.config['TEMPLATES_AUTO_RELOAD'] = True
socketio = SocketIO(app, cors_allowed_origins="*", max_http_buffer_size=1e8)
class GlobalState:
    event = threading.Event()
    g_status_list = []
    last_time = 0.0
    task_queue = deque()
    last_process = ''
    isGameBegin = True
    isReset = False
    g_times = 0
    g_cureNum = 500
    g_switch = False
    g_isRestart = True
    last_change_time = time.time()

@app.after_request
def add_no_cache_header(response):
    # 添加禁用缓存的响应头
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Pragma"] = "no-cache"
    response.headers["Expires"] = "0"
    return response

def thread_runTask():
    while True:
        if GlobalState.event.is_set():
            GlobalState.task_queue.clear()
        if len(GlobalState.task_queue) != 0:
            # 初始时间
            current_time = time.time()
            task = GlobalState.task_queue[-1]
            GlobalState.task_queue.pop()
            print(f"{task.name} 开始执行")
            GlobalState.last_process = task.name
            try:
                task.run()
            except Exception as e:
                print(f"{task.name} 执行失败,错误原因:{e}")
            cost_time = int(time.time() - current_time)
            send_status(f"{task.name} 执行完成,耗时{cost_time}秒")
            print(f"{task.name} 执行完成,耗时{cost_time}秒")
            myTimeSleep_small()
        else:
            myTimeSleep_big()
        if GlobalState.isReset:
            GlobalState.isReset = False
            cfg = read_cfg()
            if cfg['switch']:
                type = update_rungame_type()
                print(f'启动游戏{type}')
                restart_game(type)
            else:
                restart_game(0)


@app.route('/')
def index():
    return render_template('index_dongri.html')

@socketio.on('connect')
def handle_connect():
    print('Client connected')

@socketio.on('disconnect')
def handle_disconnect():
    print('Client disconnected')

def send_hint(msg):#数组信息
    emit('processing_hint', msg)

def send_todo():
    emit('processing_todo', get_todo_msgList())

def send_status(msg):#软件执行状态
    try:
        if not msg == "":
            # 添加新的状态消息和时间到列表
            timestamp = datetime.now().strftime('%H:%M:%S')  # 获取当前时间
            status_entry = {'msg': msg, 'time': timestamp}  # 存储消息和时间
            GlobalState.g_status_list.append(status_entry)

            # 如果列表超过 5 条，移除最早的一条
            if len(GlobalState.g_status_list) > 5:
                GlobalState.g_status_list.pop(0)
        else:
            sendStr = ''
            for item in GlobalState.g_status_list:
                sendStr = f"{GlobalState.g_times}次-{item['time']}-{item['msg']}<br>" + sendStr

            emit('processing_status', sendStr)
        
        # 如果消息是 "结束"，发送所有状态并清空列表
        if msg == "结束":
            GlobalState.g_status_list = []  # 清空列表
            GlobalState.event.clear()
    except Exception as e:
        print(f"Error in send_status: {e}")
        return


@socketio.on('monitor_begin')
def monitor_begin():
    current_time = time.time()
    elapsed_time = current_time - GlobalState.last_time
    if elapsed_time < 0.5:
        return
    GlobalState.last_time = current_time
    regionRet, regionPos = game_region()
    screenshot = pyautogui.screenshot(region=regionPos)
    #binary_img = binarize_image(screenshot)
    compressed_data = compress_image(screenshot)
    
    image_data_base64 = base64.b64encode(compressed_data).decode('utf-8')
    socketio.emit('image_data', image_data_base64)
    task_arr = []
    if not GlobalState.event.is_set():
        task_arr.append(GlobalState.last_process)
    for item in reversed(GlobalState.task_queue):
        task_arr.append(item.name)
    latest_tasks = task_arr[:5] # only show the last 5 tasks
    send_hint(json.dumps(latest_tasks, ensure_ascii=False))
    send_todo()
    send_status('')
    #print("send img")

@socketio.on('end_script')
def handle_end_script():
    GlobalState.event.set()

@socketio.on('end_game')
def handle_end_game():
    GlobalState.event.set()
    task_close_game()
    send_status("结束2")
    GlobalState.event.clear()

@socketio.on('get_title')
def handle_get_title():
    str = task_getComputerName()
    dst = str + ' machine'
    emit('processing_title', dst)

@socketio.on('reset_script')
def handle_reset_script():
    python = sys.executable
    while '--reset' in sys.argv:
    # 从 sys.argv 列表中删除 --reset 参数
        sys.argv.remove('--reset')
    os.execl(python, python, *sys.argv)

@socketio.on('restart_game')
def handle_restart_game():
    python = sys.executable
    script = os.path.abspath(sys.argv[0]) # 获取当前脚本的绝对路径

    # 构建新的参数列表，移除旧的 --reset 并添加新的
    new_args = [arg for arg in sys.argv[1:] if arg != '--reset'] # 排除脚本名和旧的 --reset
    
    print(f"当前 Python 解释器: {python}")
    print(f"当前脚本路径: {script}")
    print(f"重启参数: {[python, script, *new_args, '--reset']}")

    try:
        # 使用 os.execv 是一种更“彻底”的重启方式，它会替换当前进程
        # 但 subprocess.Popen 也可以，前提是旧进程退出
        # subprocess.Popen([python, script, *new_args, '--reset'])
        os.execv(python, [python, script, *new_args, '--reset'])
    except Exception as e:
        print(f"重启失败: {e}")
        # 如果 os.execv 失败，可以尝试 subprocess.Popen 作为备用
        subprocess.Popen([python, script, *new_args, '--reset'])

    sys.exit(0) # 终止当前进程

@app.route('/restart_game', methods=['POST'])
def http_restart_game():
    print("HTTP 触发 restart_game")
    socketio.start_background_task(handle_restart_game)
    return jsonify({"status": "success", "message": "已重启"})

@socketio.on('close_game')
def handle_close_game():
    task_close_game()
    send_status("结束2")
    GlobalState.event.clear()

@app.route('/close_game', methods=['POST'])
def http_close_game():
    print("HTTP 触发 close_game")
    handle_close_game()
    socketio.start_background_task(handle_reset_script)
    return jsonify({"status": "success", "message": "已关闭"})


@socketio.on('read_cfg')
def handle_read_cfg():
    cfg = read_cfg()
    emit('processing_cfg', cfg)

def restart_game(type=0):
    GlobalState.isGameBegin = False
    while True:
        task_close_game()
        if True == task_start_game(type):
            break
        else:
            send_status("启动失败")
    GlobalState.isGameBegin = True
    send_status("结束")
    config = read_cfg()
    print("config", config)
    auto_task(config)

def auto_participate():
    GlobalState.task_queue.appendleft(task_returnAllLine())

    timeout = 40 * 60
    start_time = time.time()  # 记录开始时间


    while not GlobalState.event.is_set():
        if len(GlobalState.task_queue) < 4:
            GlobalState.task_queue.appendleft(task_useAnnimalSkill(True))
            GlobalState.task_queue.appendleft(task_paticipateInTeam(False))
            GlobalState.task_queue.appendleft(task_paticipateInTeam())
            GlobalState.task_queue.appendleft(task_paticipateInTeam(False))
            GlobalState.task_queue.appendleft(task_paticipateInTeam())
        myTimeSleep_big()
        # 每次循环检查已用时间
        current_time = time.time()
        elapsed_time = current_time - start_time
        
        if elapsed_time >= timeout:
            handle_restart_game()
            break


def auto_palace():
    timeout = 180 * 60
    start_time = time.time()  # 记录开始时间
    read_cfg()
    while not GlobalState.event.is_set():
        GlobalState.g_times += 1
        if len(GlobalState.task_queue) < 4:
            GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum * 5))
            GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum * 3))
            GlobalState.task_queue.appendleft(task_fight_enemy())

        myTimeSleep_big()
        current_time = time.time()
        elapsed_time = current_time - start_time
        
        if elapsed_time >= timeout:
            handle_restart_game()

def add_auto_task(isMaxCollect, isJina, isSimple = False, isAddStrengh = False, activity = 'None', isAutoParticipate = True, isDailyConfig = False, train_type = 'None', always = False):  
    collectArr = [int(x) for x in isMaxCollect.split(",")]
    print("collectArr", collectArr)
    if len(collectArr) == 1:
        collectArr = collectArr[0]
    while not GlobalState.event.is_set():
        if isSimple == False and is_within_n_minutes(get_todo_time("巨熊行动"), 30, 35):
            print("in fight bear")
            if len(GlobalState.task_queue) < 5:
                start_recording()
                GlobalState.task_queue.appendleft(task_returnAllLine())
                GlobalState.task_queue.appendleft(task_useAnnimalSkill(True))
                GlobalState.task_queue.appendleft(task_paticipateInTeam2(not GlobalState.g_switch))
                GlobalState.task_queue.appendleft(task_paticipateInTeam2(not GlobalState.g_switch))
                GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch))
                GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch))
                GlobalState.task_queue.appendleft(task_paticipateInTeam2(not GlobalState.g_switch))
                GlobalState.task_queue.appendleft(task_paticipateInTeam2(not GlobalState.g_switch))
                GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch))
                GlobalState.task_queue.appendleft(task_paticipateInTeam(not GlobalState.g_switch))
                GlobalState.task_queue.appendleft(task_paticipateInTeam(False))
                
            myTimeSleep_big()
            send_status(f'巨熊行动中')
            continue
        elif isSimple == False and is_within_n_minutes(get_todo_time("巨熊行动"), 60, 0):
            # 设置无尽运行和启动的游戏为0
            always = True
            if GlobalState.g_switch:
                update_rungame_type(0)
            send_status(f'巨熊行动:在60min内,切换到无尽模式')
        stop_recording()
        
        print("add special activity")
        # special activity
        if activity == 'lianmeng':
            GlobalState.task_queue.appendleft(task_activity_lianmeng())
        elif activity == 'cure':
            GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum))
        elif activity == 'only_cure':
            GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum))
            GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum))
            GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum))
            return
        
        print("add normal activity")
        GlobalState.task_queue.appendleft(task_checkActivities())
        if GlobalState.g_switch == True:
            GlobalState.task_queue.appendleft(task_checkBenifitStatus())
    
            
        if isSimple == False:
            GlobalState.task_queue.appendleft(task_information())

        GlobalState.task_queue.appendleft(task_check_Research())
        GlobalState.task_queue.appendleft(task_checkStoreRoom())
        if not isSimple:
            if isJina == 'jina':
                GlobalState.task_queue.appendleft(task_fight_jina(isAddStrengh))
            elif isJina == 'yongbing':
                GlobalState.task_queue.appendleft(task_fight_yongbing(isAddStrengh))
            elif isJina == 'monster':
                GlobalState.task_queue.appendleft(task_fightMonster(isAddStrengh, False, isSimple))
            elif isJina == 'big_monster' or isJina == 'bigMonster_max':
                GlobalState.task_queue.appendleft(task_fightMonster(isAddStrengh, True, isSimple))
            elif isJina == 'jina_call':
                ### 全部聊天记录都是新吉娜
                GlobalState.task_queue.appendleft(task_call_jina())
                GlobalState.task_queue.appendleft(task_call_jina())
                GlobalState.task_queue.appendleft(task_call_jina())
                GlobalState.task_queue.appendleft(task_call_jina())
            elif isJina == 'jina_onlyFight':
                GlobalState.task_queue.appendleft(task_fight_jina_only())
        GlobalState.task_queue.appendleft(task_collect(collectArr, isSimple, isAddStrengh))
        GlobalState.task_queue.appendleft(task_train(train_type))
        
        if isSimple == False:
            if not isAddStrengh: # 如果不是添加体力，则添加一次采集
                GlobalState.task_queue.appendleft(task_collect(collectArr, isSimple, isAddStrengh))
            if isJina == 'monster' and isAddStrengh:
                GlobalState.task_queue.appendleft(task_fightMonster(isAddStrengh, False, isSimple))
            else:
                GlobalState.task_queue.appendleft(task_collect(collectArr, isSimple, isAddStrengh))
        else:
            GlobalState.task_queue.appendleft(task_collect(collectArr, isSimple, isAddStrengh))
    
        print("add rare activity")
        if GlobalState.g_times % 5 == 1:
            if get_rungame_type() == 0:
                GlobalState.task_queue.appendleft(check_buildOrResearch())
            GlobalState.task_queue.appendleft(task_cure(True, GlobalState.g_cureNum))
            GlobalState.task_queue.appendleft(task_information())
            GlobalState.task_queue.appendleft(task_checkDonata())
            GlobalState.task_queue.appendleft(task_checkMaster())
            GlobalState.task_queue.appendleft(task_checkAdventure())
            GlobalState.task_queue.appendleft(task_train(train_type))
            GlobalState.task_queue.appendleft(task_useAnnimalSkill())
            GlobalState.task_queue.appendleft(task_read_mails())
            GlobalState.task_queue.appendleft(task_getStrength())
            if auto_participate:
                GlobalState.task_queue.appendleft(task_checkConfilits())
            GlobalState.task_queue.appendleft(task_checkDiamond())
            GlobalState.task_queue.appendleft(task_fight_campion())
            GlobalState.task_queue.appendleft(task_get_fire_crystal())
            GlobalState.task_queue.appendleft(task_checkUnionTreasure())
            #GlobalState.task_queue.appendleft(task_checkBenifitStatus())
            GlobalState.task_queue.appendleft(task_gotoTree())
            GlobalState.task_queue.appendleft(task_checkHelp())

        if activity == 'redPackage':
            GlobalState.task_queue.appendleft(task_get_redPackage())
        if isJina == 'bigMonster_max':
            GlobalState.task_queue.appendleft(task_fightMonster(isAddStrengh, True, isSimple))

        print("check restart")
        GlobalState.g_times += 1
        restart_times = 7
        if GlobalState.g_switch:
            restart_times = 4
        if GlobalState.g_times % restart_times == 0 and GlobalState.g_times != 0:
            if GlobalState.g_isRestart:
                handle_end_game()
            if GlobalState.g_switch == False:
                if always:
                    nextTaskTime = random.randint(400, 450)
                    set_nextTaskTime(nextTaskTime)
                    myTimeSleep(nextTaskTime, send_status)
                else:
                    nextTaskTime = random.randint(1000, 2000)
                    set_nextTaskTime(nextTaskTime)
                    myTimeSleep(nextTaskTime, send_status)
            else:
                nextTaskTime = random.randint(20, 50)
                set_nextTaskTime(nextTaskTime)
                myTimeSleep(nextTaskTime, send_status)
            if GlobalState.g_isRestart:
                handle_restart_game()
        else:
            nextTaskTime = random.randint(400, 450)
            set_nextTaskTime(nextTaskTime)
            myTimeSleep(nextTaskTime, send_status)
            
        
    GlobalState.task_queue.clear()
    send_status(f'自动模式结束')
    GlobalState.event.clear()

daily_config = {
    "login_task": False,
    "fight_bigMonster_times": 0
}

def check_daily_config(config):

    today = datetime.now().strftime('%Y-%m-%d')  # 获取当前日期
    print(f"Today: {today}")  # 打印当前日期
    print(f"Config: {config}")  # 打印传入的配置
    
    if "daily" not in config:
        print("Daily key not found, creating it.")  # 调试信息
        config["daily"] = {}
        return False
    
    if today not in config["daily"]:
        print(f"Today's config not found: {today}")  # 调试信息
        return False
    else:
        print(f"Today's config found: {today}")  # 调试信息
        return True

def update_rungame_type(dstType=None):
    config = read_Dailycfg()
    runTypeStr = 'runType'
    if runTypeStr not in config:
        if dstType is not None:
            config[runTypeStr] = dstType
        else:
            config[runTypeStr] = 1
        write_Dailycfg(config)
        print(f"更新下次启动{config[runTypeStr]}")
        return 0
    else:
        value = config[runTypeStr]
        if dstType is not None:
            config[runTypeStr] = dstType
        else:
            config[runTypeStr] = (value + 1) % 2        
        write_Dailycfg(config)
        print(f"更新下次启动{config[runTypeStr]}")
        return value
    
def get_rungame_type():
    config = read_Dailycfg()
    runTypeStr = 'runType'
    if runTypeStr not in config:
        return 0
    else:
        if config[runTypeStr] == 0:
            return 1
        else:
            return 0

# 修改或添加 "login_task" 的值
def set_login_task(config, value):
    today = datetime.now().strftime('%Y-%m-%d')  # 获取当前日期
    if today not in config["daily"]:  # 如果当天的配置不存在
        config["daily"][today] = {}  # 创建当天的配置
    config["daily"][today]["login_task"] = value  # 设置或更新 "login_task"
    return config

# 修改或添加 "fight_bigMonster_times" 的值
def set_fight_big_monster_times(config, value):
    today = datetime.now().strftime('%Y-%m-%d')  # 获取当前日期
    if today not in config["daily"]:  # 如果当天的配置不存在
        config["daily"][today] = {}  # 创建当天的配置
    config["daily"][today]["fight_bigMonster_times"] = value  # 设置或更新 "fight_bigMonster_times"
    return config


def add_today_daily_config(config, daily_config, overwrite=False):
    today = datetime.now().strftime('%Y-%m-%d')  # 获取当前日期
    if today not in config["daily"] or overwrite:  # 如果不存在或允许覆盖
        config["daily"][today] = daily_config  # 添加或更新
    return config

# 清理非当天的每日配置
def clean_old_daily_configs(config):
    today = datetime.now().strftime('%Y-%m-%d')  # 获取当前日期
    keys_to_remove = [key for key in config["daily"] if key != today]  # 找到非当天的每日配置
    for key in keys_to_remove:
        del config["daily"][key]  # 删除非当天的每日配置
    return config

def write_cfg(config):
    with open('config.json', 'w') as config_file:
        json.dump(config, config_file, indent=4)
def read_cfg():
    try:
        with open('config.json', 'r') as config_file:
            config = json.load(config_file)
            GlobalState.g_cureNum = int(config['cureNumber'])
            return config
    except FileNotFoundError:
        print("配置文件不存在，请检查文件路径。")
        return None
    except PermissionError:
        print("没有权限读取配置文件。")
        return None
    except json.JSONDecodeError:
        print("配置文件格式错误，请检查文件内容是否为有效的 JSON。")
        return None
    
def write_Dailycfg(config):
    with open('daily.json', 'w') as config_file:
        json.dump(config, config_file, indent=4)
def read_Dailycfg():
    try:
        with open('daily.json', 'r') as config_file:
            config = json.load(config_file)
            return config
    except FileNotFoundError:
        print("配置文件不存在，请检查文件路径。")
        return None
    except PermissionError:
        print("没有权限读取配置文件。")
        return None
    except json.JSONDecodeError:
        print("配置文件格式错误，请检查文件内容是否为有效的 JSON。")
        return None

@socketio.on('begin_auto')
def handle_auto(data):
    write_cfg(data)
    config = read_cfg()
    print("config", config)
    auto_task(config)

def auto_task(data):
    if data == None:
        isMaxCollect = '4,3,2,1'
        isSimple = False
        isJina = 'jina'
        isAddStrengh = False
        activity = 'none'
        participateJijie = False
        auto_daily = False
        train_type = 'none'
        always = False
        cureNumber = 500
        lineCheck = False
        switch = False
        GlobalState.g_isRestart = True
    else:
        isMaxCollect = data['maxCollect']
        isSimple = data['simple']
        isJina = data['jina']
        isAddStrengh = data['add_strength']
        activity = data['activity']
        participateJijie = data['participate_jijie']
        auto_daily = False
        train_type = data['train']
        always = data['always']
        cureNumber = int(data['cureNumber'])
        lineCheck = data['lineCheck']
        switch = data['switch']
        GlobalState.g_isRestart = data['is_restart']

    GlobalState.g_cureNum = cureNumber
    GlobalState.g_switch = switch
    set_lineCheck(lineCheck)
    send_status(f'开始自动模式')
    executor.submit(add_auto_task, isMaxCollect, isJina, isSimple, isAddStrengh, activity, participateJijie, auto_daily, train_type, always)


@socketio.on('begin_auto_participate')
def handle_auto_participate():
    send_status(f'开始自动集结模式')
    executor.submit(auto_participate)

@socketio.on('begin_testNewFun')
def handle_auto_testNewFun():
    send_status(f'开始自动测试新功能')
    task_testFun().run()




@socketio.on('auto_palace')
def handle_auto_palace():
    send_status(f'开始自动王城')
    executor.submit(auto_palace)

def monitor_game_runtime():
    last_value = GlobalState.g_times
    
    while True:
        current_value = GlobalState.g_times
        if current_value != last_value:
            last_value = current_value
            GlobalState.last_change_time = time.time()
            print(f"g_times changed to {current_value}")
        
        # 检查是否超过60分钟没有变化
        if time.time() - GlobalState.last_change_time > 3600:  # 3600秒=60分钟
            print("g_times hasn't changed for 60 minutes!")
            handle_restart_game()
        
        time.sleep(10) 



if __name__ == '__main__':
    init()
    if '--reset' in sys.argv:
        time.sleep(2)
        GlobalState.isReset = True
        print("需要重启游戏")
    runTask = threading.Thread(target=thread_runTask)#启动线程往里面添加任务
    runTask.daemon = True
    runTask.start()

    monitor_thread = threading.Thread(target=monitor_game_runtime, daemon=True)
    monitor_thread.start()
    
    socketio.run(app, host= '0.0.0.0', debug=True, use_reloader=False)#关闭自动重载
