# -*- coding:utf-8 -*-
# Author: Liaojiang

"""
2025/3/5
海洋空战.scen
6v6+打船
蓝方bot
"""

import logging

from engine.LingYi.entitys.global_util import *
from engine.LingYi.entitys.agent_base import RuleAgentBase


class Agent(RuleAgentBase):
    def __init__(self, side_name, params):
        RuleAgentBase.__init__(self, side_name)
        logging.info('%s:%s play game' % (side_name, self.__class__.__name__))

    def set_rules(self):
        """
        设置条令、武器使用规则、电磁规则或撤退规则
        :return:
        """
        # 设置对空武器状态：自由开火
        self.doctrine_weapon_control_status_air(WeaponControlStatus.Free)
        # 设置对海武器状态：自由开火
        self.doctrine_weapon_control_status_surface(WeaponControlStatus.Free)
        # 设置武器状态返航
        self.doctrine_weapon_state_rtb(WeaponStateRTB.YesLeaveGroup)
        # 设置燃油状态返航
        self.doctrine_fuel_state_rtb(FuelStateRTB.YesLeaveGroup)

        # 设置武器使用规则
        # 51:AIM-120D型先进中程空空导弹, WRA_WeaponTargetType: 在entitys.global_util.py中定义
        self.wra_qty_salvo('51', WRA_WeaponTargetType.Air_Contact_Unknown_Type, '1')
        self.wra_qty_salvo('51', WRA_WeaponTargetType.Aircraft_Unspecified, '1')
        self.wra_firing_range('51', WRA_WeaponTargetType.Air_Contact_Unknown_Type, '50')
        self.wra_firing_range('51', WRA_WeaponTargetType.Aircraft_Unspecified, '50')
        self.wra_qty_salvo('3042', WRA_WeaponTargetType.Surface_Contact_Unknown_Type, '8')
        self.wra_qty_salvo('3042', WRA_WeaponTargetType.Ship_Unspecified, '8')

    def set_units_sensors(self, situation):
        """
        根据态势给各单元设置雷达、电子干扰等传感器开关机
        :param situation: tuple: units, contacts
        :return:
        """
        # 找到驱逐舰，使干扰传感器开机
        self.ddg_guid = ""
        for unit_id, unit in situation[0].items():
            # 遍历本分所有单元
            if unit['category'] == 'Ship' and 'DDG' in unit['name']:
                self.ddg_guid = unit_id  # 获取到驱逐舰guid
        if self.ddg_guid != "":
            ddg_ship = self.get_unit(self.ddg_guid)  # 获取驱逐舰对象
            # 驱逐舰干扰传感器开机
            ddg_ship.switch_OECM(True)  # 单元接口在unit.py中

    def add_set_missions(self, situation):
        """
        根据态势创建各种任务，并找到单元分配任务
        :param situation: tuple: units, contacts
        :return:
        """
        # 创建巡逻任务的空战巡逻任务
        self.north_patrol = self.create_patrol_mission("north_patrol", MissionPatrolType.AIR,
                                                       [(26.4, 157.53), (26.4, 157.74), (26.2, 157.74),
                                                        (26.2, 157.53)])
        self.south_patrol = self.create_patrol_mission("south_patrol", MissionPatrolType.AIR,
                                                       [(25.475, 157.53), (25.475, 157.74), (25.275, 157.74),
                                                        (25.275, 157.53)])
        # 设置巡逻任务不执行三分之一规则，任务的飞机将全部起飞
        self.north_patrol.set_one_third_rule(False)
        self.south_patrol.set_one_third_rule(False)

        # 获取4架大黄蜂, 2架闪电，对方驱逐舰位置
        self.north_huangfeng = []
        self.south_huangfeng = []
        self.lightning = []
        self.target_id = ""

        for target_id, target in situation[1].items():
            # 遍历所有获取的情报
            if target['Type'] == 2 and target['Lon'] > 154.5:
                # 找到对方驱逐舰
                self.target_id = target_id  # 情报接触的guid
                break

        huangfeng = []  # 所有大黄蜂战机
        for unit in situation[0].values():
            # 遍历本分所有单元
            if unit['category'] == 'Aircraft':
                if unit['dbid'] == 753:
                    # 是大黄蜂战机,应该有4架
                    huangfeng.append(unit["guid"])
                elif unit['dbid'] == 3836:
                    # 是闪电战机，应该有2架
                    self.lightning.append(unit["guid"])

        if len(huangfeng) == 4:
            # 给巡逻任务分配大黄蜂战机
            self.north_patrol.assign_unit(huangfeng[0])
            self.north_patrol.assign_unit(huangfeng[1])
            self.south_patrol.assign_unit(huangfeng[2])
            self.south_patrol.assign_unit(huangfeng[3])
            self.north_huangfeng = [huangfeng[0], huangfeng[1]]
            self.south_huangfeng = [huangfeng[2], huangfeng[3]]

        # 创建打击任务之对船打击，打击对对方驱逐舰任务
        attack = self.create_strike_mission('attack', MissionStrikeType.SHIP)

        # 打击任务添加目标
        attack.strike_add_target([self.target_id])
        # 设置打击任务单机编队
        attack.strike_setStrikeFlightSize(FlightSize.One)
        # 给打击任务分配飞机
        self.set_air_height = set()  # 设置F35飞机高度，超过一万米才能发射空舰导弹
        for guid in self.lightning:
            attack.assign_unit(guid)

    def initial(self, situation):
        """
        初始化函数，每局推演开始前被调用. 可用于任务创建、设置，条令设置，变量初始化等
        :param situation: tuple: units, contacts
        :return:
        """
        # 设置推演方条令、武器使用规则
        self.set_rules()

        # 根据态势给各单元设置雷达、电子干扰等传感器开关机
        self.set_units_sensors(situation)

        # 任务创建与设置
        self.add_set_missions(situation)

    def step(self, time_elapse, situation):
        """
        # 每步决策函数
        :param time_elapse:  int, time elapse
        :param situation: tuple: units-list, contacts-list
        :return:
        """
        """
        如果打掉对方船:
            闪电没有远程空空弹，返航, 否则加入空战巡逻任务
        如果大黄蜂没有远程空空弹后，不再巡逻，返航
        """
        target_id = ""
        if isinstance(situation[1], dict):
            for target_id, target in situation[1].items():
                # 遍历所有获取的情报
                if not isinstance(target, str):
                    if target['Type'] == 2 and target['Lon']  > 154.5:
                        # 找到对方驱逐舰
                        target_id = target_id  # 情报接触的guid
                        break

        # 设置F35飞机高度，超过一万米才能发射空舰导弹
        if len(self.set_air_height) < len(self.lightning):
            for guid in self.lightning:
                air = self.get_unit(guid)
                if air is not None:
                    if air.Lon < 157:
                        air.set_alt_manual(True)
                        air.set_desired_height(12000.0)  # 设置飞机期望高度，单元接口在unit.py中
                        self.set_air_height.add(guid)  # 临近目标时，仅需设置一次

        if target_id == "":
            # 没有找到对方驱逐舰，因为驱逐舰是自动获知情报，说明对方船已被摧毁
            for unit in situation[0].values():
                # 遍历本方所有单元
                if unit['category'] == 'Aircraft':
                    air = self.get_unit(unit['guid'])
                    if air is not None:
                        weapon_info = air.get_weapon_info()
                    else:
                        continue
                    if unit['dbid'] == 3836:
                        # 是闪电战机
                        if 51 in weapon_info and weapon_info[51] > 0:
                            # 还有远程空空弹，加入巡逻任务
                            self.north_patrol.assign_unit(unit['guid'])
                        else:
                            # 返航
                            self.unit_return_to_base(unit['guid'])
                    else:
                        # 大黄蜂没有远程空空弹后，不再巡逻，返航
                        if not (51 in weapon_info and weapon_info[51] > 0):
                            # 返航
                            self.unit_return_to_base(unit['guid'])

    def deduction_end(self):
        # agent结束后自动被调用函数， 可保存模型，比如记录本局策略后的得分等
        logging.info('%s:%s play game result:%d' % (self.Name, self.__class__.__name__, self.TotalScore))

    def is_done(self):
        # agent主动结束本局推演，比如一定胜利或失败后
        # 只能训练时调用此函数，比赛对战时此函数不可用
        if self.TotalScore >= 1500 or self.TotalScore <= -1500:
            return True
        return False

