#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/8/3 17:53
# @Author : Opfer
# @Site :
# @File : redispatch.py    
# @Software: PyCharm

from flask import Flask, request
from flask.json import jsonify
from para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
from core.dispatcher import Dispatcher, PreSchedule
from core.group import Group
from flask_caching import Cache
from alg.algorithm import ExpectedTime
from data.dispatchInfo import DispatchInfo
from core.dispatcher import DispatchSubmission
from graph_load import graph_construct

config = {
    "DEBUG": True,          # some Flask specific configs
    "CACHE_TYPE": "SimpleCache",  # Flask-Caching related configs
    "CACHE_DEFAULT_TIMEOUT": 300
}

app = Flask(__name__)
app.config.from_mapping(config)
cache = Cache(app)


def update_truck_loacate(truck_id):
    # 读取矿卡所在路段信息
    try:
        truck_locate_dict = {}
        device_name_set = redis2.keys()
        for item in device_name_set:
            item = item.decode(encoding='utf-8')
            # json_value = json.loads(redis2.get(item))
            key_value_dict = redis2.hgetall(item)
            device_type = key_value_dict[str_to_byte('type')]
            is_online = key_value_dict[str_to_byte('online')]
            key_set = key_value_dict.keys()
            if (device_type == str_to_byte("1")) \
                    and (str_to_byte('online') in key_set) \
                    and (bytes.decode(is_online) in ["true" or "True"]) \
                    and (str_to_byte('laneId') in key_set):
                truck_locate = key_value_dict[str_to_byte('laneId')]
                truck_locate_dict[get_value("truck_name_to_uuid_dict")[item]] = eval(truck_locate)
    except Exception as es:
        logger.error(" ")

    return truck_locate_dict[truck_id]


@app.route("/redispatch", methods=["POST"])
def dispatch_request():

    # 获取报文数据
    data_json = request.get_json()

    # 车辆id
    truck_id = data_json.get("truck_id")

    # 调度开始时间
    rtd_start_time = datetime.now()

    # 初始化日志
    set_log()
    # 获取日志器
    logger = get_logger("zxt.truck-request")

    # 更新周期参数
    logger.info("#####################################请求调度更新开始#####################################")

    try:

        # 清空数据库缓存
        session_mysql.commit()
        session_mysql.flush()

        # 清空数据库缓存
        session_postgre.commit()
        session_postgre.flush()
    except Exception as es:
        logger.error("数据库访问异常")
        logger.error(es)
        return jsonify(msg="未知异常, 请联系管理员", code=501)

    try:

        # 全局参数更新
        global_period_para_update()
        # get_global_para_from_cache(cache)

    except Exception as es:
        logger.error("全局参数更新异常")
        logger.error(es)
        session_mysql.rollback()
        session_postgre.rollback()
        return jsonify(msg="未知异常, 请联系管理员", code=502)

    try:
        # 更新调度信息
        DispatchInfo.reset()

        DispatchInfo.update_device_group_structure()

        if group_id not in DispatchInfo.truck_group_dict:
            raise Exception("请求调度车辆不存在")

        DispatchInfo.update_route_distance()

        DispatchInfo.update_group_mode()

        DispatchInfo.update_group_name()
    except Exception as es:
        logger.error("调度信息更新异常")
        logger.error(es)
        session_mysql.rollback()
        session_postgre.rollback()
        return jsonify(msg="未知异常, 请联系管理员", code=503)

    logger.info("Dispatchinfo，更新后信息")
    logger.info("group_set")
    logger.info(DispatchInfo.group_set)
    logger.info("group_excavator_dict")
    logger.info(DispatchInfo.group_excavator_dict)
    logger.info("group_unload_area_dict")
    logger.info(DispatchInfo.group_unload_area_dict)
    logger.info("group_truck_dict")
    logger.info(DispatchInfo.group_truck_dict)
    logger.info("group_mode")
    logger.info(DispatchInfo.group_mode)
    logger.info("load_distance")
    logger.info(DispatchInfo.load_distance)
    logger.info("unload_distance")
    logger.info(DispatchInfo.unload_distance)

    try:

        # 实例化设备对象
        dump = DumpInfo()
        excavator = ExcavatorInfo()
        truck = TruckInfo(dump, excavator)

        group_id = DispatchInfo.truck_group_dict[truck_id]

        # 设备信息更新
        dump.dump_para_period_update()
        excavator.excavator_para_period_update()
        truck.truck_para_period_update(dump, excavator)
        truck.state_period_update()

        # 实例化调度预测器
        pre_sch = PreSchedule(truck, excavator, dump)

        # 实例化输出器
        submission = DispatchSubmission(dump, excavator, truck)

        # 实例化调度分组
        group = Group(group_id, truck, pre_sch)

        # 更新调度分组信息
        group.info_update()

        truck_trip = truck.get_truck_current_trip()[truck.truck_uuid_to_index_dict[truck_id]]
        truck_task = truck.get_truck_current_task()[truck_id]

        truck_lane = update_truck_loacate(truck_id)

        excavators = DispatchInfo.group_excavator_dict[group_id]
        dumps = DispatchInfo.dump_group_dict[group_id]

        topo = graph_construct()

        next_target = None

        if truck_task in [-2, 0]:

            excavator_distance_dict = topo.get_load_target_node_real(truck_lane, None)
            MAX_DIS = 100000000
            for excavator_id in excavators:
                if excavator_distance_dict[excavator_id] < MAX_DIS:
                    next_target = excavator_id
                    MAX_DIS = excavator_distance_dict[excavator_id]

        elif truck_task == 3:
            dump_distance_dict = topo.get_unload_target_node_real(truck_lane, None)
            MAX_DIS = 100000000
            for dump_id in dumps:
                if dump_distance_dict[dump_id] < MAX_DIS:
                    next_target = dump_id
                    MAX_DIS = dump_distance_dict[dump_id]


    except Exception as es:
        logger.error("对象实例化异常")
        logger.error(es)
        session_mysql.rollback()
        session_postgre.rollback()
        return jsonify(msg="未知异常, 请联系管理员", code=504)

    try:

        # 调度分组派车计划计算
        try:
            truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
        except Exception as es:
            logger.error(es)
            logger.error(f'分组{group.group_id} 调度计算异常')

        try:

            logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
            submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
        except Exception as es:
            logger.error(es)
            logger.error(f'分组{group.group_id} 调度写入异常')

    except Exception as es:
        logger.error("最外层异常捕获")
        logger.error(es)
        return jsonify(msg="未知异常, 请联系管理员", code=505)

    session_mysql.close()
    session_postgre.close()

    logger.info("#####################################请求调度更新结束#####################################")

    # 调度结束时间
    rtd_end_time = datetime.now()

    print(f'调度时耗 {rtd_end_time - rtd_start_time}')

    return jsonify(msg="success", code=0)