# -*- coding: utf-8 -*-
from flask import Flask, render_template
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="*")
event = threading.Event()
g_status_list = []
last_time = 0.0
task_queue = deque()
last_process = ''
isGameBegin = True
autoTask = None
isReset = False
g_times = 0
g_cureNum = 500
g_switch = False

@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():
    global last_process
    global task_queue,isReset
    while True:
        if event.is_set():
            task_queue.clear()
        if len(task_queue) != 0:
            # 初始时间
            current_time = time.time()
            task = task_queue[-1]
            task_queue.pop()
            last_process = task.name
            task.run()
            cost_time = int(time.time() - current_time)
            send_status(f"{task.name} 执行完成,耗时{cost_time}秒")
            myTimeSleep_small()
        else:
            myTimeSleep_big()
        if isReset:
            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):#软件执行状态
    global g_status_list, g_times
    try:
        if not msg == "":
            # 添加新的状态消息和时间到列表
            timestamp = datetime.now().strftime('%H:%M:%S')  # 获取当前时间
            status_entry = {'msg': msg, 'time': timestamp}  # 存储消息和时间
            g_status_list.append(status_entry)

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

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


@socketio.on('monitor_begin')
def monitor_begin():
    global last_time, last_process
    current_time = time.time()
    elapsed_time = current_time - last_time
    if elapsed_time < 0.5:
        return
    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 event.is_set():
        task_arr.append(last_process)
    for item in reversed(task_queue):
        task_arr.append(item.name)
    send_hint(json.dumps(task_arr, ensure_ascii=False))
    send_todo()
    send_status('')
    #print("send img")

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

@socketio.on('end_game')
def handle_end_game():
    event.set()
    task_close_game()
    send_status("结束2")
    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
    os.execl(python, python, *sys.argv, '--reset')

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


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

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

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

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


    while not event.is_set():
        if len(task_queue) < 4:
            task_queue.appendleft(task_paticipateInTeam())
            task_queue.appendleft(task_paticipateInTeam())
            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_ranshuang():
    timeout = 40 * 60
    start_time = time.time()  # 记录开始时间
    while not event.is_set():
        if len(task_queue) < 4:
            task_queue.appendleft(task_fight_ranshuang())

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

def auto_palace():
    global g_times, g_cureNum
    timeout = 180 * 60
    start_time = time.time()  # 记录开始时间
    read_cfg()
    while not event.is_set():
        if len(task_queue) < 4:
            task_queue.appendleft(task_cure(True, g_cureNum))
            task_queue.appendleft(task_cure(True, g_cureNum))
            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):  
    global g_times, g_cureNum
    collectArr = [int(x) for x in isMaxCollect.split(",")]
    print("collectArr", collectArr)
    while not event.is_set():
        isLoginTask = True
        fight_big_monster_times = 0
        config = read_Dailycfg()
        print("config", config)
        g_times += 1
        
        if check_daily_config(config):
            today = datetime.now().strftime('%Y-%m-%d')
            isLoginTask = bool(config['daily'][today]["login_task"])
            fight_big_monster_times = int(config['daily'][today]["fight_bigMonster_times"])
        else:
            set_login_task(config, False)
            set_fight_big_monster_times(config, 0)
            clean_old_daily_configs(config)
            isLoginTask = False
            fight_big_monster_times = 0
            write_Dailycfg(config)

        send_status(f"isLoginTask:{isLoginTask}, fight_big_monster_times:{fight_big_monster_times}")


        if not isLoginTask:
            task_queue.appendleft(task_checkMaster())
            set_login_task(config, True)
            write_Dailycfg(config)
        
        if isDailyConfig and fight_big_monster_times < 10:
            isSuccess = task_fightMonster(isAddStrengh, True, isSimple)
            if isSuccess:
                set_fight_big_monster_times(config, fight_big_monster_times + 1)
                write_Dailycfg(config)
        
        if is_within_n_minutes(get_todo_time("巨熊行动"), 60, 0):
            # 设置无尽运行和启动的游戏为0
            always = True
            update_rungame_type(0)
            send_status(f'巨熊行动:在60min内,切换到无尽模式')
            g_times = 2
            task_queue.appendleft(task_checkActivities())
        elif is_within_n_minutes(get_todo_time("巨熊行动"), 10, 40):
            task_queue.appendleft(task_returnAllLine())
            if len(task_queue) < 5:
                task_queue.appendleft(task_paticipateInTeam())
                task_queue.appendleft(task_paticipateInTeam())
                task_queue.appendleft(task_paticipateInTeam())
            myTimeSleep_big()
            send_status(f'巨熊行动中')
            g_times = 2
            continue
        

        # special activity
        if activity == 'lianmeng':
            task_queue.appendleft(task_activity_lianmeng())
        elif activity == 'cure':
            task_queue.appendleft(task_cure(True, g_cureNum))
        elif activity == 'only_cure':
            task_queue.appendleft(task_cure(True, g_cureNum))
            task_queue.appendleft(task_cure(True, g_cureNum))
            task_queue.appendleft(task_cure(True, g_cureNum))
            return
        # first run
        if g_times % 3 == 1:
            task_queue.appendleft(check_safe_collect())
            if get_rungame_type() == 0:
                task_queue.appendleft(task_checkActivities())
            
        if isSimple == False:
            task_queue.appendleft(task_information())

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

        
        
        task_queue.appendleft(task_gotoTree())
        #task_queue.appendleft(task_get_redPackage())
        restart_times = 7
        global g_switch
        if g_switch:
            restart_times = 4
        if g_times == restart_times:
            handle_end_game()
            if always:
                myTimeSleep(random.randint(350, 400), send_status)
            else:
                myTimeSleep(random.randint(1000, 2000), send_status)
            handle_restart_game()
        else:
            if isAddStrengh:
                myTimeSleep(random.randint(350, 400), send_status)
            else:
                myTimeSleep(random.randint(350, 400), send_status)
            
        
    task_queue.clear()
    send_status(f'自动模式结束')
    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:
        return config[runTypeStr]

# 修改或添加 "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():
    global g_cureNum
    try:
        with open('config.json', 'r') as config_file:
            config = json.load(config_file)
            g_cureNum = 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):
    global autoTask, g_cureNum
    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
        
        
    else:
        isMaxCollect = data['maxCollect']
        isSimple = data['simple']
        isJina = data['jina']
        isAddStrengh = data['add_strength']
        activity = data['activity']
        participateJijie = data['participate_jijie']
        auto_daily = data['auto_daily']
        train_type = data['train']
        always = data['always']
        cureNumber = data['cureNumber']
        lineCheck = data['lineCheck']
        switch = data['switch']

    g_cureNum = cureNumber
    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():
    global autoTask
    send_status(f'开始自动集结模式')
    executor.submit(auto_participate)

@socketio.on('begin_auto_ranshuang')
def handle_auto_ranshuang():
    global autoTask
    send_status(f'开始自动燃霜')
    executor.submit(auto_ranshuang)

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


if __name__ == '__main__':
    init()
    if '--reset' in sys.argv:
        isReset = True
        print("需要重启游戏")
    runTask = threading.Thread(target=thread_runTask)#启动线程往里面添加任务
    runTask.daemon = True
    runTask.start()
    
    socketio.run(app, host= '0.0.0.0', debug=True)
