local mod = get_mod("TaintedDevices_markers")
local HudElementWorldMarkers = require("scripts/ui/hud/elements/world_markers/hud_element_world_markers")
local Pickups = require("scripts/settings/pickup/pickups")
local HUDElementInteractionSettings = require("scripts/ui/hud/elements/interaction/hud_element_interaction_settings")
local WorldMarkerTemplateInteraction = require("scripts/ui/hud/elements/world_markers/templates/world_marker_template_interaction")
local UIWidget = require("scripts/managers/ui/ui_widget")

-- FoundYa Compatibility (Adds relevant marker categories and uses FoundYa distances instead.)
local FoundYa = get_mod("FoundYa")
mod.on_all_mods_loaded = function()
    FoundYa = get_mod("FoundYa") -- grab again incase of load order issues
end

mod.get_max_distance = function()
    local max_distance = mod:get("max_distance")

    -- foundya Compatibility
    if FoundYa ~= nil then
        max_distance = FoundYa:get("max_distance_book") or mod:get("max_distance") or 30
    end

    if max_distance == nil then
        max_distance = mod:get("max_distance") or 30
    end

    return max_distance
end

mod:hook_safe(
    CLASS.HudElementWorldMarkers, "_calculate_markers", function(self, dt, t, input_service, ui_renderer, render_settings)

        if self then
            local markers_by_type = self._markers_by_type

            for marker_type, markers in pairs(markers_by_type) do
                for i = 1, #markers do
                    local marker = markers[i]
                    if not marker.scale then
                        marker.scale = 1
                    end
                    mod.update_TaintedDevices_markers(self, marker)
                end
            end
        end
    end
)

mod.update_TaintedDevices_markers = function(self, marker)
    local max_distance = mod.get_max_distance()

    if marker and self then
        local unit = marker.unit

        local pickup_type = mod.get_marker_pickup_type(marker)

        if pickup_type then
            local pickup = Pickups.by_name[pickup_type]

            if pickup then
                local is_hack_device = false
                if pickup.name and pickup.name == "communications_hack_device" then
                    is_hack_device = true
                end
                if is_hack_device then

                    marker.draw = false
                    marker.widget.alpha_multiplier = 0

                    marker.widget.style.ring.color = Color.citadel_auric_armour_gold(nil, true)

                    marker.widget.style.icon.color = {255, 255, 255, 242, 0}
                    marker.widget.style.background.color = Color.citadel_abaddon_black(nil, true)
                    marker.template.check_line_of_sight = mod:get("require_line_of_sight")

                    marker.template.screen_clamp = mod:get("keep_on_screen")
                    marker.block_screen_clamp = false

                    -- marker.widget.content.is_clamped = false

                    -- set scale
                    local scale_settings = {}
                    scale_settings["scale_from"] = mod:get("min_size") or 0.4
                    scale_settings["scale_to"] = mod:get("max_size") or 1
                    scale_settings["distance_max"] = 15
                    scale_settings["distance_min"] = 1
                    scale_settings["easing_function"] = math.easeCubic
                    marker.scale = self._get_scale(self, scale_settings, marker.distance) or 1
                    self._apply_scale(self, marker.widget, marker.scale)

                    local max_spawn_distance_sq = max_distance * max_distance
                    HUDElementInteractionSettings.max_spawn_distance_sq = max_spawn_distance_sq

                    self.max_distance = max_distance

                    if self.fade_settings then
                        self.fade_settings.distance_max = max_distance
                        self.fade_settings.distance_min = max_distance - self.evolve_distance * 2
                    end

                    marker.template.max_distance = max_distance
                    marker.template.fade_settings.distance_max = max_distance
                    marker.template.fade_settings.distance_min = marker.template.max_distance - marker.template.evolve_distance * 2

                    local pickup_name = Unit.has_data(unit, "pickup_type") and Unit.get_data(unit, "pickup_type")

                    local max_distance = mod.get_max_distance()

                    self.max_distance = max_distance

                    if self.fade_settings then
                        self.fade_settings.distance_max = max_distance
                        self.fade_settings.distance_min = max_distance - self.evolve_distance * 2
                    end

                    marker.widget.content.icon = "content/ui/materials/hud/interactions/icons/pocketable_default"

                    marker.widget.style.icon.color = {255, mod:get("tainted_colour_R"), mod:get("tainted_colour_G"), mod:get("tainted_colour_B")}

                    if mod:get("require_line_of_sight") == true then
                        if marker.widget.content.line_of_sight_progress == 1 then
                            if marker.widget.content.is_inside_frustum or marker.template.screen_clamp then
                                marker.widget.alpha_multiplier = mod:get("alpha")
                                marker.draw = true
                            else
                                marker.widget.alpha_multiplier = 0
                                marker.draw = false
                            end
                        end
                    else
                        if marker.widget.content.is_inside_frustum or marker.template.screen_clamp then
                            marker.widget.alpha_multiplier = mod:get("alpha")
                            marker.draw = true

                        else
                            marker.widget.alpha_multiplier = 0
                            marker.draw = false
                        end
                    end
                end
            end
        end
    end
end

mod.get_marker_pickup_type = function(marker)
    if marker.type ~= "interaction" or not marker.unit or not Unit or not Unit.alive(marker.unit) or not Unit.has_data(marker.unit, "pickup_type") then
        return
    end
    return Unit.get_data(marker.unit, "pickup_type")
end

HudElementWorldMarkers._get_scale = function(self, scale_settings, distance)

    if distance and scale_settings then
        local easing_function = scale_settings.easing_function

        if distance > scale_settings.distance_max then
            return scale_settings.scale_from
        elseif distance < scale_settings.distance_min then
            return scale_settings.scale_to
        else
            local distance_fade_fraction = 1 - (distance - scale_settings.distance_min) / (scale_settings.distance_max - scale_settings.distance_min)
            local eased_distance_scale_fraction = easing_function and easing_function(distance_fade_fraction) or distance_fade_fraction
            local adjusted_fade = scale_settings.scale_from + eased_distance_scale_fraction * (scale_settings.scale_to - scale_settings.scale_from)

            return adjusted_fade
        end
    else
        return 1
    end
end

HudElementWorldMarkers._get_fade = function(self, fade_settings, distance)
    if fade_settings and distance then
        local easing_function = fade_settings.easing_function
        local return_value

        if distance > fade_settings.distance_max then
            return_value = fade_settings.fade_from
        elseif distance < fade_settings.distance_min then
            return_value = fade_settings.fade_to
        else
            local distance_fade_fraction = 1 - (distance - fade_settings.distance_min) / (fade_settings.distance_max - fade_settings.distance_min)
            local eased_distance_fade_fraction = easing_function(distance_fade_fraction)
            local adjusted_fade = fade_settings.fade_from + eased_distance_fade_fraction * (fade_settings.fade_to - fade_settings.fade_from)

            return_value = adjusted_fade
        end

        if fade_settings.invert then
            return 1 - return_value
        else
            return return_value
        end
    else
        return 1
    end
end

HudElementWorldMarkers._draw_markers = function(self, dt, t, input_service, ui_renderer, render_settings)
    local camera = self._camera

    if camera then
        local markers_by_type = self._markers_by_type

        for marker_type, markers in pairs(markers_by_type) do
            for i = 1, #markers do
                local marker = markers[i]
                local draw = marker.draw

                if draw then
                    local widget = marker.widget
                    local content = widget.content
                    local distance = content.distance
                    local template = marker.template
                    local scale_settings = template.scale_settings
                    local fade_settings = template.fade_settings

                    if scale_settings then
                        marker.scale = self:_get_scale(scale_settings, distance)

                        local new_scale = marker.ignore_scale and 1 or marker.scale

                        self:_apply_scale(widget, new_scale)
                    end

                    local alpha_multiplier = 1

                    if fade_settings and not marker.block_fade_settings and distance then
                        alpha_multiplier = self:_get_fade(fade_settings, distance)
                    end

                    if draw then
                        local previous_alpha_multiplier = widget.alpha_multiplier

                        widget.alpha_multiplier = (previous_alpha_multiplier or 1) * alpha_multiplier

                        UIWidget.draw(widget, ui_renderer)

                        widget.alpha_multiplier = previous_alpha_multiplier
                    end
                end
            end
        end
    end
end
