# -*- coding: utf-8 -*-
# @Time : 2022/5/30 14:45
# @Author : Opfer
# @Site :
# @File : dispatchInfo.py
# @Software: PyCharm
import numpy as np

from settings import *
import pandas as pd

logger = get_logger("mqc.dispatchInfo")


class DispatchInfo:
    """
    class for dispatch group info.
    """
    # dispatch groups
    group_set = set()

    # device group structure
    load_excavator_dict = {}  # 装载区id-->>电铲编号的映射
    excavator_load_dict = {}  # 电铲编号->>装载区id的映射

    group_excavator_dict = {}  # team_id -> dict {[excavator_id, excavator_id], ...}
    excavator_group_dict = {}  # excavator_id -> team_id   问题：多个key值对应一个value值

    group_dump_dict = {}  # team_id -> dict {unload_area_id, unload_area_id, ...}
    dump_group_dict = {}  # unload_area_id -> team_id

    group_truck_dict = {}  # team_id -> dict # {group_id:[truck_id,truck_id],...}
    truck_group_dict = {}  # truck_id -> team_id

    # group feature
    group_mode = {}  # 数据格式： {team_id:mode_code}

    # route_distance（路网距离）
    load_distance = {}
    unload_distance = {}

    @classmethod
    def renew_set(cls):
        """
        @date：2022/6/2 19:50
        @author：maqc
        @desc：实例化对象，可直接访问
        """
        cls.group_set = set()

        cls.load_excavator_dict = {}
        cls.excavator_load_dict = {}

        cls.group_excavator_dict = {}
        cls.excavator_group_dict = {}

        cls.group_dump_dict = {}
        cls.dump_group_dict = {}

        cls.group_truck_dict = {}
        cls.truck_group_dict = {}

        cls.group_mode = {}

        cls.load_distance = {}
        cls.unload_distance = {}

        # cls.group_dump_dict = {}   # cls.group_dump_dict.keys() 相当于所有的team_id
        # cls.dump_group_dict = {}  # cls.dump_group_dict.keys() 相当于所有的卸载区 unload_area_id
        # cls.group_excavator_dict = {}
        # cls.excavator_group_dict = {}
        # cls.load_excavator_dict = {}  # cls.load_excavator_dict.keys() 相当于所有的装载区 load_area_id
        # cls.excavator_load_dict = {}
        # cls.group_truck_dict = {}
        # cls.truck_group_dict = {}
        # cls.group_mode = {}
        # cls.load_distance = {}  # to_load_diatance-->>空车模式
        # cls.unload_distance = {}  # to_unload_distance-->>重车模式

    @classmethod
    def update_device_group_structure(cls):
        """
        @date：2022/6/2 19:49
        @author：maqc
        @desc：分组与卸载区、挖机、矿卡的映射和反映射
        """
        logger = get_logger("mqc.update_device_group_structure")


        # build excavator group map
        try:
            for item in session_postgre.query(DiggingWorkArea).all():

                if item.ExactorUuid is not None:
                    cls.load_excavator_dict[str(item.Id)] = item.ExactorUuid
                    cls.excavator_load_dict[item.ExactorUuid] = str(item.Id)
        except Exception as es:
            logger.error("挖机和装载区映射更新异常")
            logger.error(es)

        # update excavator<->group and dump<->group map
        try:
            for item in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():

                # if item.group_code not in cls.group_excavator_dict.keys():
                #     cls.group_excavator_dict[item.group_code] = item.excavator_id
                # else:
                #     cls.group_excavator_dict[item.group_code].append(item.excavator_id)
                # cls.excavator_group_dict[item.excavator_id] = item.group_code
                if item.load_area_id is not None and item.dump_id is not None:
                    if item.group_code not in cls.group_excavator_dict.keys():
                        cls.group_excavator_dict[item.group_code] = [item.exactor_id]
                    else:
                        cls.group_excavator_dict[item.group_code].append(item.exactor_id)
                    cls.excavator_group_dict[item.exactor_id] = item.group_code

                    if item.group_code not in cls.group_dump_dict.keys():
                        cls.group_dump_dict[item.group_code] = [item.unload_area_id]
                    else:
                        cls.group_dump_dict[item.group_code].append(item.unload_area_id)
                    cls.dump_group_dict[item.unload_area_id] = item.group_code
        except Exception as es:
            logger.error("挖机/卸载区与group_id映射更新异常")
            logger.error(es)

        # update truck<->group map
        try:
            for item in session_mysql.query(DispatchEquipment).filter_by(group_type=1).all():
                if item.group_code not in cls.group_truck_dict.keys():
                    cls.group_truck_dict[item.group_code] = [item.equipment_id]
                else:
                    cls.group_truck_dict[item.group_code].append(item.equipment_id)
                cls.truck_group_dict[item.equipment_id] = item.group_code
        except Exception as es:
            logger.error("矿卡与group_id映射更新异常")
            logger.error(es)

        # update group set
        try:
            cls.group_set = set(cls.group_excavator_dict.keys())
        except Exception as es:
            logger.error(es)

        # try:
        #     # group_dump_dict = {} -->> {team_id:[unload_area_id,unload_area_id],...}
        #     # dump_group_dict = {}  # unload_area_id -> team_id
        #     group_code_dict = {}  # group_code-->>team_id的映射
        #     for valve in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
        #         group_code_dict[valve.group_code] = valve.team_id
        #         if valve.team_id not in cls.group_dump_dict:
        #             cls.group_dump_dict[valve.team_id] = [valve.unload_area_id]  # 注意：一个team_id可能对应多个unload_area_id
        #         else:
        #             cls.group_dump_dict[valve.team_id].append(valve.unload_area_id)
        #         cls.dump_group_dict[valve.unload_area_id] = valve.team_id  # 一个unload_area_id只对应一个team_id
        #     # group_excavator_dict = {} -->>  {team_id: [excavator_id, excavator_id], ...}  # 一个team_id对应一组excavator_id, unload_area_id
        #     # excavator_group_dict = {} -->>  excavator_id -> team_id  一个excavator_id只对应一个team_id
        #     for item in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
        #         if item.team_id in cls.group_excavator_dict:
        #             cls.group_excavator_dict[item.team_id].append(item.excavator_id)
        #         else:
        #             cls.group_excavator_dict[item.team_id] = [item.excavator_id]
        #         cls.excavator_group_dict[item.excavator_id] = item.team_id
        #     # group_truck_dict = {} -->> {team_id:[truck_id,truck_id],...}
        #     # truck_group_dict = {} -->> truck_id -> team_id
        #     for key in session_mysql.query(DispatchEquipment).filter_by(group_type=1).all():
        #         if key.group_code in group_code_dict:
        #             if key.group_code not in cls.group_truck_dict:
        #                 cls.group_truck_dict[key.group_code] = [key.equipment_id]
        #             else:
        #                 cls.group_truck_dict[key.group_code].append(key.equipment_id)
        #             cls.truck_group_dict[key.equipment_id] = group_code_dict[key.group_code]

        # except Exception as es:
        #     logger.error("分组到卸载区的数据更新异常")
        #     logger.error(es)

    @classmethod
    def update_group_mode(cls):
        """
        @date：2022/6/2 19:49
        @author：maqc
        @desc：处理其它类型的数据
        """
        # update group_id->mode_code
        logger = get_logger("mqc.update_group_mode")
        cls.group_mode = {}
        try:
            for item in session_mysql.query(DispatchGroup).all():
                mode_id = item.mode_id
                mode_code = session_mysql.query(DispatchMode).filter_by(id=mode_id).first().mode_code
                # mode = session_mysql.query(DispatchMode).filter_by(group_code=).first()
                cls.group_mode[item.id] = mode_code
        except Exception as es:
            logger.error("group_id->mode_code更新异常")
            logger.error(es)

        # 新增：team_id-->>group_code;group_code-->>mode_code.结果：team_id-->>mode_code
        # team_group_dict = {}  # team_id-->>group_code的一个映射，格式：{team_id:group_code}
        # group_mode_dict = {}  # group-->>mode_code的一个映射，格式：{group_code:mode_code}
        # try:
        #     for pos in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
        #         team_group_dict[pos.team_id] = pos.group_code
        #     for item in session_mysql.query(DispatchGroup).filter_by(group_type=1).all():
        #         group_mode_dict[item.group_code] = item.mode_code
        #     for key, value in team_group_dict.items():
        #         if value in group_mode_dict:
        #             cls.group_mode[key] = group_mode_dict[value]
        # except Exception as es:
        #     logger.error("派车模式数据更新异常")
        #     logger.error(es)

    # @classmethod
    # def dispatch_group_init(cls):
    #     """
    #     update basic paras (group_set, dict, num ...)
    #     :return:
    #     """
    #     try:
    #         for value in session_postgre.query(DiggingWorkArea).all():
    #             cls.load_excavator_dict[value.Id] = value.ExactorId
    #             cls.excavator_load_dict[value.ExactorId] = value.Id
    #     except Exception as es:
    #         logger.error("初始化数据更新异常")
    #         logger.error(es)
    @classmethod
    # 距离-->>数据格式：矩阵-->>to_load_distance
    def update_route_distance(cls):
        """
        @date：2022/6/2 19:50
        @author：maqc
        @desc：更新路网距离，返回矩阵格式数据
        """
        logger = get_logger("mqc.update_route_distance")
        try:
            groups = cls.group_excavator_dict.keys()
            for item in groups:
                # 每个组的 excavator_id
                excavator_ids = cls.group_excavator_dict[item]
                # 每个组的load_areas
                load_areas = []
                for excavator_id in excavator_ids:
                    load_areas.append(cls.excavator_load_dict[excavator_id])
                # 每个组的unload_areas
                unload_areas = cls.group_dump_dict[item]

                # unload->load 路网
                unload_load_distance = np.zeros((len(unload_areas), len(load_areas)))
                for i in range(len(unload_areas)):
                    for j in range(len(load_areas)):
                        distance = int(session_postgre.query(WalkTime).filter_by(unload_area_id=unload_areas[i], load_area_id=load_areas[j]).first().to_load_distance)
                        unload_load_distance[i][j] = distance
                cls.load_distance[item] = unload_load_distance

                # load->unload 路网
                load_unload_distance = np.zeros((len(load_areas), len(unload_areas)))
                for i in range(len(load_areas)):
                    for j in range(len(unload_areas)):
                        distance = int(session_postgre.query(WalkTime).filter_by(load_area_id=load_areas[i], unload_area_id=unload_areas[j]).first().to_unload_distance)
                        load_unload_distance[i][j] = distance
                cls.unload_distance[item] = load_unload_distance

        except Exception as es:
            logger.error("路网距离更新异常")
            logger.error(es)


        #     try:
        #         df = pd.DataFrame()  # 记录装载区与卸载区之间的距离
        #         for item in session_postgre.query(WalkTime).all():
        #             temp = str(item.load_area_id), str(item.unload_area_id), item.to_load_distance, item.to_unload_distance
        #             df = pd.concat([df, pd.DataFrame([temp])], axis=0, ignore_index=True)
        #     except Exception as es:
        #         logger.error("路网距离数据更新异常1")
        #         logger.error(es)
        #
        #     # 距离矩阵
        #     for team_id in list(cls.group_dump_dict.keys()):
        #         unload_nums = list(set(cls.group_dump_dict[team_id]))  # 获取同一个team_id对应的卸载区列表
        #         exactor_nums = list(set(cls.group_excavator_dict[team_id]))  # 获取同一个team_id对应的电铲列表
        #
        #         unload_exactor_matrix = np.zeros(
        #             (len(unload_nums), len(exactor_nums)))  # 初始化距离矩阵，记录从卸载区-->>电铲的距离，即to_load_distance，空车模式
        #         load_exactor_matrix = np.array(
        #             unload_exactor_matrix).T  # 初始化距离矩阵，记录从装载区-->>电铲的距离，即to_unload_distance，重车模式
        #
        #         try:
        #             for i in range(len(unload_nums)):
        #                 for j in range(len(exactor_nums)):
        #                     id = set(df.loc[df[1] == str(unload_nums[i])].index.to_list()) & set(
        #                         df.loc[df[0] == str(cls.excavator_load_dict[j])].index.to_list())  # 集合属性
        #                     unload_exactor_matrix[i][j] = df.iloc[list(id)[0]][2]
        #         except Exception as es:
        #             logger.error("路网距离数据更新异常2")
        #             logger.error(es)
        #
        #         try:
        #             for m in range(len(exactor_nums)):
        #                 for n in range(len(unload_nums)):
        #                     id = set(df.loc[df[0] == str(cls.excavator_load_dict[m])].index.to_list()) & set(
        #                         df.loc[df[1] == str(unload_nums[n])].index.to_list())
        #                     load_exactor_matrix[m][n] = df.iloc[list(id)[0]][3]
        #         except Exception as es:
        #             logger.error("路网距离数据更新异常3")
        #             logger.error(es)
        #         cls.load_distance[team_id] = unload_exactor_matrix
        #         cls.unload_distance[team_id] = load_exactor_matrix
        #
        # except Exception as es:
        #     logger.error("路网距离数据更新异常4")
        #     logger.error(es)

    @classmethod
    def get_group_mode(cls, group_id):
        return cls.group_mode[group_id]

    @classmethod
    def get_excavator(cls, group_id):
        return cls.group_excavator_dict[group_id]

    @classmethod
    def get_dump(cls, group_id):
        return cls.group_dump_dict[group_id]

    @classmethod
    def get_truck_set(cls, group_id):
        return cls.group_truck_dict[group_id]

    @classmethod
    def get_load_area(cls, excavator_id):
        return cls.excavator_load_dict[excavator_id]

    @classmethod
    def get_to_excavator_distance(cls, group_id):
        return cls.load_distance[group_id]

    @classmethod
    def get_to_dump_distance(cls, group_id):
        return cls.unload_distance[group_id]


    @classmethod
    def get_park_to_excavator_distance(cls, group_id):
        excavators = cls.group_excavator_dict[group_id]
        park_matrix = np.zeros((1, len(excavators)))
        for i in range(len(excavators)):
            load_area_id = cls.excavator_load_dict[excavators[i]]
            distance = session_postgre.query(WalkTimePark).filter_by(load_area_id=load_area_id).first().park_load_distance
            park_matrix[0][i] = distance
        return park_matrix


# #!E:\Pycharm Projects\Waytous
# # -*- coding: utf-8 -*-
# # @Time : 2022/5/30 14:45
# # @Author : Opfer
# # @Site :
# # @File : dispatchInfo.py
# # @Software: PyCharm
# from settings import *
#
# logger = get_logger("mqc.dispatchInfo")
#
#
# class DispatchInfo:
#     """
#     class for dispatch group info.
#     """
#
#     # dispatch groups
#     group_set = set()
#
#     # device group structure
#     group_dump_dict = {}  # team_id -> dict {unload_area_id, unload_area_id, ...}
#     # {group_id:unload_area_id,...}
#     group_excavator_dict = {}  # team_id -> dict {[excavator_id, load_area_id], ...}
#     # {group_id: [excavator_id, unload_area_id], ...}
#     group_truck_dict = {}  # team_id -> dict {truck_id, ...}
#     # {group_id:[truck_id,truck_id],...}
#
#     dump_group_dict = {}  # unload_area_id -> team_id
#     excavator_group_dict = {}  # excavator_id -> team_id
#     truck_group_dict = {}  # truck_id -> team_id
#
#     # group feature
#     group_mode = {}  # 四种模式：全智能、空车智能、定铲定铲和分流配比模式
#     # {mode_name:mode_code}
#
#     # route_distance（路网距离）
#     load_excavator_distance = {}  # 装载区-挖机（电铲）的距离  数据格式 -->> {load_area_id:[excavator_uuid, to_load_distance],}
#     unload_excavator_distance = {}  # 卸载区-挖机（电铲）的距离 数据格式 -->> {unload_area_id:[excavator_uuid, to_unload_distance],}
#
#     @classmethod
#     def renew_set(cls):
#         """
#         @date：2022/6/2 19:50
#         @author：maqc
#         @desc：实例化对象，可直接访问
#         """
#         cls.group_dump_dict = {}
#         cls.dump_group_dict = {}
#
#         cls.group_excavator_dict = {}
#         cls.excavator_group_dict = {}
#
#         cls.group_truck_dict = {}
#         cls.truck_group_dict = {}
#
#         cls.group_mode = {}
#         cls.load_excavator_distance = {}
#         cls.unload_excavator_distance = {}
#
#     @classmethod
#     def update_device_group_structure(cls):
#         """
#         @date：2022/6/2 19:49
#         @author：maqc
#         @desc：分组与卸载区、挖机、矿卡的映射和反映射
#         """
#         logger = get_logger("mqc.update_device_group_structure")
#         try:
#             # group_dump_dict = {} -->> {group_id:unload_area_id,...}
#             # dump_group_dict = {}  # unload_area_id -> team_id
#             group_code_dict = {}  # group_code-->>team_id的映射
#             for valve in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
#                 group_code_dict[valve.group_code] = valve.team_id
#                 if valve.team_id not in cls.group_dump_dict:
#                     cls.group_dump_dict[valve.team_id] = [valve.unload_area_id]  # 注意：一个team_id可能对应多个unload_area_id
#                 else:
#                     cls.group_dump_dict[valve.team_id].append(valve.unload_area_id)
#                     cls.dump_group_dict[valve.unload_area_id] = valve.team_id  # 一个unload_area_id只对应一个team_id
#             # group_excavator_dict = {} -->>  {group_id: [excavator_id, unload_area_id], ...}  # 一个team_id对应一组excavator_id, unload_area_id
#             # excavator_group_dict = {} -->>  excavator_id -> team_id  一个excavator_id只对应一个team_id
#             for item in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
#                 # cls.group_excavator_dict[item.team_id] = [item.excavator_id, item.unload_area_id]
#                 cls.group_excavator_dict[item.team_id] = item.excavator_id
#                 cls.excavator_group_dict[item.excavator_id] = item.team_id
#             # group_truck_dict = {} -->> {group_id:[truck_id,truck_id],...}
#             # truck_group_dict = {} -->> truck_id -> team_id
#             for key in session_mysql.query(DispatchEquipment).filter_by(group_type=1).all():
#                 if key.group_code in group_code_dict:
#                     if key.group_code not in cls.group_truck_dict:
#                         cls.group_truck_dict[key.group_code] = [key.equipment_id]
#                     else:
#                         cls.group_truck_dict[key.group_code].append(key.equipment_id)
#                     cls.truck_group_dict[key.equipment_id] = group_code_dict[key.group_code]
#         except Exception as es:
#             logger.error("分组到卸载区的数据更新异常")
#             logger.error(es)
#
#     @classmethod
#     def update_group_mode(cls):
#         """
#         @date：2022/6/2 19:49
#         @author：maqc
#         @desc：处理其它类型的数据
#         """
#         logger = get_logger("mqc.update_group_mode")
#         try:
#             for value in session_mysql.query(DispatchMode).all():
#                 cls.group_mode[value.mode_name] = value.mode_code
#         except Exception as es:
#             logger.error("派车模式数据更新异常")
#             logger.error(es)
#
#     @classmethod
#     def dispatch_group_init(cls):
#         """
#         update basic paras (group_set, dict, num ...)
#         :return:
#         """
#         pass
#
#
#     @classmethod
#     def get_group_road_info(cls,group_id, truck_info):
#         if truck_info == 1:
#             for i in group_excavator():
#                 pass
#                 for j in group_dump():
#                     pass
#         if truck_info == 2:
#             pass
#     @classmethod
#     # 距离-->>数据格式：矩阵-->>to_load_distance
#     def update_route_distance(cls):
#         """
#         @date：2022/6/2 19:50
#         @author：maqc
#         @desc：更新路网距离，返回矩阵格式数据
#         """
#         load_excavator_dict = {}  # 装载区id-->>电铲编号的映射
#         logger = get_logger("mqc.update_route_distance")
#         try:
#             for value in session_postgre.query(DiggingWorkArea).all():
#                 load_excavator_dict[value.Id] = value.Exactorld
#             for value in session_postgre.query(WalkTime).all():
#                 if value.load_area_id in load_excavator_dict:
#                     cls.load_excavator_distance[value.load_area_id] = [load_excavator_dict[value.load_area_id],
#                                                                        value.to_load_distance]
#                     cls.unload_excavator_distance[value.unload_area_id] = [load_excavator_dict[value.load_area_id],
#                                                                            value.to_unload_distance]
#         except Exception as es:
#             logger.error("路网数据更新异常")
#             logger.error(es)
#
#



