#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/6/1 16:35
# @Author : Opfer
# @Site :
# @File : dispatcher.py    
# @Software: PyCharm

from data.dispatchInfo import DispatchInfo
from core.group import Group
from alg.algorithm import ExpectedTime
from settings import get_logger, session_mysql, redis5
from tables import Dispatch
from para_config import DeviceMap, get_value, global_period_para_update
from equipment import TruckInfo, ExcavatorInfo, DumpInfo
from core.schedule import PreSchedule
import json
import numpy as np
from datetime import datetime, timedelta


class Dispatcher:
    """
    class for group dispatch program.
    """
    def __init__(self, truck: TruckInfo, dump: DumpInfo, excavator: ExcavatorInfo, pre_sch: PreSchedule, request_mode=False):
        self.group_list = []
        self.truck = truck
        self.dump = dump
        self.excavator = excavator
        self.submission = DispatchSubmission(dump, excavator, truck)

    def period_update(self):
        """
        Update global parameter and equipment information.
        :return: None
        """

        # global_period_para_update()

        self.dump.dump_para_period_update()
        self.excavator.excavator_para_period_update()
        self.truck.truck_para_period_update(self.dump, self.excavator)
        self.truck.state_period_update()

    def group_generate(self):
        """
        Generate and initialize dispatch groups.
        :return: None
        """
        for group_id in DispatchInfo.group_dump_dict.keys():
            group = Group(group_id, self.truck)
            self.group_list.append(group)

    def group_dispatch(self):
        """
        Group dispatching logic.
        :return:
        """
        for group in self.group_list:
            truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
            self.submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)


class DispatchSubmission:
    """ class for the submission calculated dispatch.

    Description:
        将调度结果按照指定格式传递到云端机群
    Attribute:

    """
    def __init__(self, dump, excavator, truck):
        self.logger = self.logger = get_logger("zxt.submission")
        self.dump = dump
        self.excavator = excavator
        self.truck = truck

    def truck_dispatch_to_redis(self, truck_id, dispatch_seq):
        """
        将truck_id对应矿卡派车计划写入redis
        :param truck_id: (uuid) 矿卡uuid
        :param dispatch_seq: (List[int]) 矿卡派车计划
        :return: None
        """
        try:
            try:
                group_id = self.group.dispatch_truck_group[truck_id]

                record = {"truckId": truck_id}
                task = self.truck.get_truck_current_task()[truck_id]
            except Exception as es:
                self.logger.error("调度结果写入异常-读取矿卡信息异常(uuid, group id, task)")
                self.logger.error(es)

            if task in [0, 1, 2]:  # 卡车空载或在装载区出场前, 可变更卸载目的地
                try:
                    item = (
                        session_mysql.query(Dispatch)
                            .filter_by(dump_id=DeviceMap.dump_index_to_uuid_dict[dispatch_seq[1]],
                                       exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[0]],
                                       truck_id=truck_id,
                                       group_id=group_id,
                                       isauto=1, isdeleted=0, ).first())
                    if item is None:
                        raise Exception("调度计划表与实时监控不匹配")
                except Exception as es:
                    self.logger.error(es)
                    item = (
                        session_mysql.query(Dispatch)
                            .filter_by(truck_id=truck_id,
                                       # group_id=group_id,
                                       isauto=1, isdeleted=0, ).first())

                try:
                    record["exactorId"] = item.exactor_id
                    record["dumpId"] = item.dump_id
                    record["loadAreaId"] = item.load_area_id
                    record["unloadAreaId"] = item.unload_area_id
                    record["dispatchId"] = item.id
                    record["isdeleted"] = False
                    record["creator"] = item.creator
                    record["createtime"] = item.createtime.strftime(
                        "%b %d, %Y %I:%M:%S %p")

                    redis5.set(truck_id, str(json.dumps(record)))
                except Exception as es:
                    self.logger.error("调度结果写入异常-矿卡空载")
            elif task in [3, 4, 5]:  # 卡车重载或在卸载区出场前, 可变更装载目的地
                try:
                    item = (
                        session_mysql.query(Dispatch)
                            .filter_by(exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]],
                                       dump_id=DeviceMap.dump_index_to_uuid_dict[dispatch_seq[0]],
                                       truck_id=truck_id,
                                       group_id=group_id,
                                       isauto=1, isdeleted=0, ).first())
                    if item is None:
                        raise Exception("调度计划表与实时监控不匹配")
                except Exception as es:
                    self.logger.error(es)
                    item = (
                        session_mysql.query(Dispatch)
                            .filter_by(truck_id=truck_id,
                                       # group_id=group_id,
                                       isauto=1, isdeleted=0, ).first())
                try:
                    record["exactorId"] = self.excavator.excavator_index_to_uuid_dict[dispatch_seq[1]]
                    record["dumpId"] = item.dump_id
                    record["loadAreaId"] = item.load_area_id
                    record["unloadAreaId"] = item.unload_area_id
                    record["dispatchId"] = item.id
                    record["isdeleted"] = False
                    record["creator"] = item.creator
                    record["createtime"] = item.createtime.strftime(
                        "%b %d, %Y %I:%M:%S %p")

                    redis5.set(truck_id, str(json.dumps(record)))
                except Exception as es:
                    self.logger.error("调度结果写入异常-矿卡重载")
            elif task == -2:
                try:
                    try:
                        item = (
                            session_mysql.query(Dispatch)
                                .filter_by(exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]],
                                           truck_id=truck_id,
                                           group_id=group_id,
                                           isauto=1, isdeleted=0).first())

                        if item is None:
                            raise Exception("调度计划表与实时监控不匹配")

                        self.logger.info(dispatch_seq)
                        self.logger.info(dispatch_seq[1])
                        self.logger.info(DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]])

                        self.logger.info("item")
                        print(item.id, item.truck_id, item.exactor_id, item.dump_id)
                    except Exception as es:
                        self.logger.error(es)
                        item = (
                            session_mysql.query(Dispatch)
                                .filter_by(truck_id=truck_id,
                                           # group_id=group_id,
                                           isauto=1, isdeleted=0).first())

                    try:
                        record["exactorId"] = item.exactor_id
                        record["dumpId"] = item.dump_id
                        record["loadAreaId"] = item.load_area_id
                        record["unloadAreaId"] = item.unload_area_id
                        record["dispatchId"] = item.id
                        record["isdeleted"] = False
                        record["creator"] = item.creator
                        record["createtime"] = item.createtime.strftime(
                            "%b %d, %Y %I:%M:%S %p")

                        redis5.set(truck_id, str(json.dumps(record)))

                    except Exception as es:
                        self.logger.error("调度结果写入异常-矿卡故障或备停区-redis写入异常")
                        self.logger.error(es)

                except Exception as es:
                    self.logger.error("调度结果写入异常-矿卡故障或备停区")
                    self.logger.error(es)
            else:
                pass

        except Exception as es:
            self.logger.error("调度结果写入异常")
            self.logger.error(f"调度结果:{dispatch_seq}")
            self.logger.error(es)

    def group_dispatch_to_redis(self, group: Group, dispatch_plan_dict):
        """
        Update the dispatch plan in the group to redis
        :param group: (Group)
        :param dispatch_plan_dict: (Dict)
        :return: None
        """
        for truck_id, dispatch_plan in dispatch_plan_dict:
            self.truck_dispatch_to_redis(truck_id, dispatch_plan)

