import random
import math
from .conflictgen import *
from .naming import *

from dcs.mission import *

DISTANCE_FACTOR = 0.5, 1
EXTRA_AA_MIN_DISTANCE = 50000
EXTRA_AA_MAX_DISTANCE = 150000
EXTRA_AA_POSITION_FROM_CP = 550


def num_sam_dead(sam_type, destroyed_count):
    """
    Given a type and count of SAM units, determine if enough units were destroyed to warrant the
     loss of a site
    :param sam_type:
        inidivudal unit name in SAM site which was destroyed
    :param destroyed_count:
        count of that unit type which was destroyed *in the sortie*
    :return:
        INT: number of sites lost
    """
    sam_threshold = {
        AirDefence.SAM_SR_P_19: 1,
        AirDefence.SAM_SA_3_S_125_TR_SNR: 1,
        AirDefence.SAM_SA_6_Kub_STR_9S91: 1,
        AirDefence.SAM_SA_10_S_300PS_SR_5N66M: 1,
        AirDefence.SAM_SA_10_S_300PS_TR_30N6: 1,
        AirDefence.SAM_SA_10_S_300PS_CP_54K6: 1,
        AirDefence.SAM_SA_10_S_300PS_SR_64H6E: 1,
        AirDefence.SAM_SA_3_S_125_LN_5P73: 4,
        AirDefence.SAM_SA_6_Kub_LN_2P25: 6,
        AirDefence.SAM_SA_10_S_300PS_LN_5P85C: 8,
        AirDefence.SAM_SA_2_LN_SM_90:4,
        AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song: 1,
        AirDefence.SAM_Hawk_PCP: 1,
        AirDefence.SAM_Hawk_LN_M192: 4,
        AirDefence.SAM_Hawk_SR_AN_MPQ_50: 1,
        AirDefence.SAM_Hawk_TR_AN_MPQ_46: 1
    }

    return int(destroyed_count / sam_threshold[sam_type])


def determine_positions(position, heading, num_units, launcher_distance, coverage=90):
    """
    Given a position on the map, array a group of units in a circle a uniform distance from the unit
    :param position:
        position of the center unit
    :param heading:
        the direction the units should be arranged toward if coverage is not 360
    :param num_units:
        number of units to play on the circle
    :param launcher_distance:
        distance the units should be from the center unit
    :param coverage:
        0-360
    :return:
        list of tuples representing each unit location
            [(pos_x, pos_y, heading), ...]
    """
    if coverage == 360:
        # one of the positions is shared :'(
        outer_offset = coverage / num_units
    else:
        outer_offset = coverage / (num_units - 1)

    positions = []

    if num_units % 2 == 0:
        current_offset = heading - ((coverage / (num_units - 1)) / 2)
    else:
        current_offset = heading
    current_offset -= outer_offset * (math.ceil(num_units / 2) - 1)
    for x in range(1, num_units + 1):
        positions.append((
            position.x + launcher_distance * math.cos(math.radians(current_offset)),
            position.y + launcher_distance * math.sin(math.radians(current_offset)),
            current_offset,
        ))
        current_offset += outer_offset
    return positions


def aaa_vehicle_group(self, country, name, _type: unittype.VehicleType, position: mapping.Point,
                  heading=0, group_size=1,
                  formation=unitgroup.VehicleGroup.Formation.Line,
                  move_formation: PointAction=PointAction.OffRoad):
    """
    Override the default vehicle group so that our group can contain a mix of units (which is required for advanced
        SAM sites)
    For further docstrings, see the built-in function
    """
    vg = unitgroup.VehicleGroup(self.next_group_id(), self.string(name))

    for i in range(1, group_size + 1):
        heading = randint(0, 359)
        if _type == AirDefence.SAM_SA_3_S_125_LN_5P73:
            # 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR
            num_launchers = 4
            # search radar
            v = self.vehicle(
                name + " Unit #{nr}-sr".format(nr=i),
                AirDefence.SAM_SR_P_19,
            )
            v.position.x = position.x
            v.position.y = position.y + (i - 1) * 20
            v.heading = heading
            vg.add_unit(v)
            # track radar
            v = self.vehicle(
                name + " Unit #{nr}-tr".format(nr=i),
                AirDefence.SAM_SA_3_S_125_TR_SNR,
            )

            center_x = position.x + randint(20, 40)
            center_y = position.y + (i - 1) * 20

            v.position.x = center_x
            v.position.y = center_y
            v.heading = heading
            vg.add_unit(v)
            plop_positions = determine_positions(
                position,
                heading,
                num_launchers,
                launcher_distance=100,
                coverage=180,
            )
            for x in range(0, num_launchers):
                v = self.vehicle(
                    name + " Unit #{nr}-{x}".format(nr=i, x=x),
                    AirDefence.SAM_SA_3_S_125_LN_5P73,
                )

                v.position.x = plop_positions[x][0]
                v.position.y = plop_positions[x][1]
                v.heading = plop_positions[x][2]
                vg.add_unit(v)

        elif _type == AirDefence.SAM_SA_6_Kub_LN_2P25:
            # 6 launchers (360 degree coverage)
            # 1 S/TR
            # search/track radar
            num_launchers = 6
            v = self.vehicle(
                name + " Unit #{nr}-str".format(nr=i),
                AirDefence.SAM_SA_6_Kub_STR_9S91,
            )
            v.position.x = position.x
            v.position.y = position.y + (i - 1) * 20
            v.heading = heading
            vg.add_unit(v)

            plop_positions = determine_positions(
                position,
                heading,
                num_launchers,
                launcher_distance=100,
                coverage=360,
            )
            for x in range(0, num_launchers):
                v = self.vehicle(
                    name + " Unit #{nr}-{x}".format(nr=i, x=x),
                    AirDefence.SAM_SA_6_Kub_LN_2P25,
                )

                v.position.x = plop_positions[x][0]
                v.position.y = plop_positions[x][1]
                v.heading = plop_positions[x][2]
                vg.add_unit(v)
        elif _type == AirDefence.SAM_SA_10_S_300PS_LN_5P85C:
            # 8 launchers - 4 directions, two in each direction
            # 1 SR (offset)
            # 1 TR (center)
            # search radar
            num_launchers = 8
            v = self.vehicle(
                name + " Unit #{nr}-sr".format(nr=i),
                AirDefence.SAM_SA_10_S_300PS_SR_5N66M,
            )
            v.position.x = position.x
            v.position.y = position.y + (i - 1) * 20
            v.heading = heading
            vg.add_unit(v)
            # track radar
            v = self.vehicle(
                name + " Unit #{nr}-tr".format(nr=i),
                AirDefence.SAM_SA_10_S_300PS_TR_30N6,
            )

            center_x = position.x + randint(20, 40)
            center_y = position.y + (i - 1) * 20

            v.position.x = center_x
            v.position.y = center_y
            v.heading = heading
            vg.add_unit(v)

            # command center
            v = self.vehicle(
                name + " Unit #{nr}-c".format(nr=i),
                AirDefence.SAM_SA_10_S_300PS_CP_54K6,
            )

            center_x = position.x + randint(40, 60)
            center_y = position.y + (i - 1) * 20

            v.position.x = center_x
            v.position.y = center_y
            v.heading = heading
            vg.add_unit(v)

            plop_positions = determine_positions(
                position,
                heading,
                num_launchers,
                launcher_distance=150,
                coverage=360,
            )
            for x in range(0, num_launchers):
                v = self.vehicle(
                    name + " Unit #{nr}-{x}".format(nr=i, x=x),
                    AirDefence.SAM_SA_10_S_300PS_LN_5P85C,
                )

                v.position.x = plop_positions[x][0]
                v.position.y = plop_positions[x][1]
                v.heading = plop_positions[x][2]
                vg.add_unit(v)

        elif _type == AirDefence.SAM_SA_10_S_300PS_CP_54K6:
            # 8 launchers - 4 directions, two in each direction
            # 1 SR (offset)
            # 1 TR (center)
            # search radar
            num_launchers = 8
            v = self.vehicle(
                name + " Unit #{nr}-sr".format(nr=i),
                AirDefence.SAM_SA_10_S_300PS_SR_64H6E,
            )
            v.position.x = position.x
            v.position.y = position.y + (i - 1) * 20
            v.heading = heading
            vg.add_unit(v)
            # track radar
            v = self.vehicle(
                name + " Unit #{nr}-tr".format(nr=i),
                AirDefence.SAM_SA_10_S_300PS_TR_30N6,
            )

            center_x = position.x + randint(20, 40)
            center_y = position.y + (i - 1) * 20

            v.position.x = center_x
            v.position.y = center_y
            v.heading = heading
            vg.add_unit(v)

            # command center
            v = self.vehicle(
                name + " Unit #{nr}-c".format(nr=i),
                AirDefence.SAM_SA_10_S_300PS_CP_54K6,
            )

            center_x = position.x + randint(40, 60)
            center_y = position.y + (i - 1) * 20

            v.position.x = center_x
            v.position.y = center_y
            v.heading = heading
            vg.add_unit(v)

            plop_positions = determine_positions(
                position,
                heading,
                num_units=num_launchers,
                launcher_distance=150,
                coverage=360,
            )
            for x in range(0, num_launchers):
                v = self.vehicle(
                    name + " Unit #{nr}-{x}".format(nr=i, x=x),
                    AirDefence.SAM_SA_10_S_300PS_LN_5P85D,
                )

                v.position.x = plop_positions[x][0]
                v.position.y = plop_positions[x][1]
                v.heading = plop_positions[x][2]
                vg.add_unit(v)
        elif _type == AirDefence.SAM_Hawk_PCP:
            # 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR, 1 PCP
            num_launchers = 4

            # search radar
            v = self.vehicle(
                name + " Unit #{nr}-sr".format(nr=i),
                AirDefence.SAM_Hawk_SR_AN_MPQ_50,
            )
            v.position.x = position.x
            v.position.y = position.y + (i - 1) * 20
            v.heading = heading
            vg.add_unit(v)


            # track radar
            v = self.vehicle(
                name + " Unit #{nr}-tr".format(nr=i),
                AirDefence.SAM_Hawk_TR_AN_MPQ_46,
            )
            center_x = position.x + randint(20, 40)
            center_y = position.y + (i - 1) * 20
            v.position.x = center_x
            v.position.y = center_y
            v.heading = heading
            vg.add_unit(v)

            # PCP
            v = self.vehicle(
                name + " Unit #{nr}-pcp".format(nr=i),
                AirDefence.SAM_Hawk_PCP,
            )

            center_x = position.x + randint(60, 80)
            center_y = position.y + 20
            v.position.x = center_x
            v.position.y = center_y
            v.heading = heading
            vg.add_unit(v)

            plop_positions = determine_positions(
                position,
                heading,
                num_launchers,
                launcher_distance=100,
                coverage=180,
            )
            for x in range(0, num_launchers):
                v = self.vehicle(
                    name + " Unit #{nr}-{x}".format(nr=i, x=x),
                    AirDefence.SAM_Hawk_LN_M192,
                )

                v.position.x = plop_positions[x][0]
                v.position.y = plop_positions[x][1]
                v.heading = plop_positions[x][2]
                vg.add_unit(v)
        elif _type == AirDefence.SAM_SA_2_LN_SM_90:
            # 4 launchers (180 degrees all facing the same direction), 1 SR, 1 TR
            num_launchers = 4

            # search radar
            v = self.vehicle(
                name + " Unit #{nr}-sr".format(nr=i),
                AirDefence.SAM_SR_P_19,
            )
            v.position.x = position.x
            v.position.y = position.y + (i - 1) * 20
            v.heading = heading
            vg.add_unit(v)


            # track radar
            v = self.vehicle(
                name + " Unit #{nr}-tr".format(nr=i),
                AirDefence.SAM_SA_2_TR_SNR_75_Fan_Song,
            )
            center_x = position.x + randint(20, 40)
            center_y = position.y + (i - 1) * 20
            v.position.x = center_x
            v.position.y = center_y
            v.heading = heading
            vg.add_unit(v)

            plop_positions = determine_positions(
                position,
                heading,
                num_launchers,
                launcher_distance=100,
                coverage=180,
            )
            for x in range(0, num_launchers):
                v = self.vehicle(
                    name + " Unit #{nr}-{x}".format(nr=i, x=x),
                    AirDefence.SAM_SA_2_LN_SM_90,
                )

                v.position.x = plop_positions[x][0]
                v.position.y = plop_positions[x][1]
                v.heading = plop_positions[x][2]
                vg.add_unit(v)
        else:
            v = self.vehicle(name + " Unit #{nr}-sam".format(nr=i), _type)
            v.position.x = position.x
            v.position.y = position.y + (i - 1) * 20
            v.heading = heading
            vg.add_unit(v)

    wp = vg.add_waypoint(vg.units[0].position, move_formation, 0)
    wp.ETA_locked = True
    if _type.eplrs:
        wp.tasks.append(task.EPLRS(self.next_eplrs("vehicle")))

    country.add_vehicle_group(vg)
    return vg


class AAConflictGenerator:
    def __init__(self, mission: Mission, conflict: Conflict):
        self.m = mission
        self.conflict = conflict

    def generate_at_defenders_location(self, units: db.AirDefenseDict):
        for unit_type, count in units.items():
            for _ in range(count):
                self.m.vehicle_group(
                    country=self.conflict.defenders_country,
                    name=namegen.next_unit_name(self.conflict.defenders_country, unit_type),
                    _type=unit_type,
                    position=self.conflict.ground_defenders_location.random_point_within(100, 100),
                    group_size=1)

    def generate(self, units: db.AirDefenseDict):
        for type, count in units.items():
            for _, radial in zip(range(count), self.conflict.radials):
                distance = randint(self.conflict.size * DISTANCE_FACTOR[0] + 9000, self.conflict.size * DISTANCE_FACTOR[1] + 14000)
                p = self.conflict.position.point_from_heading(random.choice(self.conflict.radials), distance)

                self.m.aaa_vehicle_group(
                        country=self.conflict.defenders_country,
                        name=namegen.next_unit_name(self.conflict.defenders_country, type),
                        _type=type,
                        position=p,
                        group_size=1)


class ExtraAAConflictGenerator:
    def __init__(self, mission: Mission, conflict: Conflict, game, player_country: Country, enemy_country: Country):
        self.mission = mission
        self.game = game
        self.conflict = conflict
        self.player_country = player_country
        self.enemy_country = enemy_country

    def generate(self):
        from theater.conflicttheater import ControlPoint

        for cp in self.game.theater.controlpoints:
            if cp.is_global:
                continue

            if cp.position.distance_to_point(self.conflict.position) < EXTRA_AA_MIN_DISTANCE:
                continue

            if cp.position.distance_to_point(self.conflict.from_cp.position) < EXTRA_AA_MIN_DISTANCE:
                continue

            if cp.position.distance_to_point(self.conflict.to_cp.position) < EXTRA_AA_MIN_DISTANCE:
                continue

            if cp.position.distance_to_point(self.conflict.position) > EXTRA_AA_MAX_DISTANCE:
                continue

            country_name = cp.captured and self.player_country or self.enemy_country
            position = cp.position.point_from_heading(0, EXTRA_AA_POSITION_FROM_CP)

            self.mission.vehicle_group(
                country=self.mission.country(country_name),
                name=namegen.next_basedefense_name(),
                _type=db.EXTRA_AA[country_name],
                position=position,
                group_size=1
            )

