package com.dowstats.data.entities.weapon

import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.WeaponDto
import com.dowstats.data.dto.controllers.WeaponShortDto
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.sergant.SergeantWeapon
import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.building.BuildingWeapon
import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.unit.UnitWeapon
import jakarta.persistence.*


@Entity
@Table(name = "weapons")
class Weapon {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long? = null
    var filename: String? = null
    var name: String? = null
    var description: String? = null
    var costRequisition: Double? = null
    var costPower: Double? = null
    var costTimeSeconds: Double? = null
    var accuracy: Double? = null
    var reloadTime: Double? = null
    var minRange: Double? = null
    var maxRange: Double? = null
    var setupTime: Double? = null
    var accuracyReductionMoving: Double? = null
    var minDamage: Double? = null
    var maxDamage: Double? = null
    var minDamageValue: Double? = null
    var moraleDamage: Double? = null
    var damageRadius: Double? = null
    var throwForceMin: Double? = null
    var throwForceMax: Double? = null
    var isMeleeWeapon: Boolean = true
    var canAttackAir: Boolean = true
    var canAttackGround: Boolean = true
    var uiHotkeyName: String? = null
    var icon: String? = null
    var showInReinforce: Boolean = true
    var modId: Long? = null

    @ManyToMany
    @JoinTable(name = "researches_affected_weapons",
        joinColumns = [JoinColumn(name = "weapon_id")],
        inverseJoinColumns = [JoinColumn(name = "research_id")])
    var affectedResearches: MutableSet<Research> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "addon_affected_weapons",
        joinColumns = [JoinColumn(name = "weapon_id")],
        inverseJoinColumns = [JoinColumn(name = "addon_id")])
    var affectedAddons: MutableSet<BuildingAddon> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "building_affected_weapons",
        joinColumns = [JoinColumn(name = "weapon_id")],
        inverseJoinColumns = [JoinColumn(name = "building_id")])
    var affectedBuildings: MutableSet<Building> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "ability_affected_weapons",
        joinColumns = [JoinColumn(name = "weapon_id")],
        inverseJoinColumns = [JoinColumn(name = "ability_id")])
    var affectedAbilities: MutableSet<Ability> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "sergeant_affected_weapons",
        joinColumns = [JoinColumn(name = "weapon_id")],
        inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
    var affectedSergeants: MutableSet<Sergeant> = mutableSetOf()

    @ManyToMany
    @JoinTable(name = "unit_affected_weapons",
        joinColumns = [JoinColumn(name = "weapon_id")],
        inverseJoinColumns = [JoinColumn(name = "unit_id")])
    var affectedUnits: MutableSet<DowUnit> = mutableSetOf()

    @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
    var unitsUse: MutableSet<UnitWeapon>? = null

    @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
    var sergeantsUse: MutableSet<SergeantWeapon>? = null

    @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
    var buildingUse: MutableSet<BuildingWeapon>? = null

    // for many-to-many persistance
    data class HardpointPosition(val weaponId: Long, val hardpoint: Int, val order: Int)

    @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
    var weaponModifiers: MutableSet<WeaponModifiers> = mutableSetOf()

    @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
    var weaponRequirements: MutableSet<WeaponRequirements> = mutableSetOf()


    @OneToMany(mappedBy="weapon", cascade = [(CascadeType.ALL)])
    var weaponPiercings: List<WeaponArmorPiercing> = listOf()

    fun toDto(requirementDto: RequirementDto?) = WeaponDto(
        id!!,
        filename!!,
        name,
        description,
        costRequisition,
        costPower,
        costTimeSeconds,
        accuracy,
        reloadTime,
        minRange,
        maxRange,
        setupTime,
        accuracyReductionMoving,
        minDamage,
        maxDamage,
        minDamageValue,
        moraleDamage,
        damageRadius,
        throwForceMin,
        throwForceMax,
        isMeleeWeapon,
        canAttackAir,
        canAttackGround,
        icon,
        showInReinforce,
        modId,
        weaponPiercings.map { it.toDto() },
        affectedResearches.map { it.toResearchShortDto() }.toSet(),
        affectedAddons.map { it.toShortDto() }.toSet(),
        weaponModifiers.map { mod -> mod.toDto().copy(maxLifeTime = mod.maxLifeTime) },
        requirementDto,
        uiHotkeyName,
    )

    fun toShortDto() = WeaponShortDto(
        id!!,
        filename!!,
        name,
        icon,
        isMeleeWeapon,
    )
}
