---@diagnostic disable: undefined-field
require "Vehicles/ISUI/ISVehicleDashboard"
require "Vehicles/Vehicles"

NepHBO7 = {}

NepHBO7.options = {
	activationKey   = nil, -- NepHBO7.options.activationKey:getValue()

    --fixHeadlights = nil,   -- NepHBO7.options.fixHeadlights:getValue()
    debugMode = nil,       -- NepHBO7.options.debugMode:getValue()
    printErrors = true;   --just a normal value, not mod options
    -- note on dotSize: --rear > 0 avoids flickering, or <-0.75 if you want the car lit up
    -- dot 0= 180° glow, dot -1=360° glow

    alwaysOn = nil,  -- NepHBO7.options.alwaysOn:getValue()

    lengthMult = nil, --NepHBO7.options.lengthMult:getValue()
    intensityMult= nil, --NepHBO7.options.intensityMult:getValue()

    --glowWhenHBOn = nil,--NepHBO7.options.glowWhenHBOn:getValue()   
    --glowWhenHBOff = nil,--NepHBO7.options.glowWhenHBOff:getValue()   
    --overrideDot = true, 
    --overrideDotValue = 0.8, --0,96 is the default
    --overrideFocus=8, --10 is default for fully healthy headlights, 1 is a circle
    radialMenu = nil, -- NepHBO7.options.radialMenu:getValue()
    radialTextureOn=getTexture("media/ui/NepHighbeamOn.png"),
    radialTextureOff=getTexture("media/ui/NepHighbeamOff.png"),

}

NepHBO7.headlightParts={ --the number is xoffset mutlipier
    HeadlightLeft =  1,
    HeadlightRight = -1
}

NepHBO7.vanilla = { -- from VehicleUtils.initHeadlight(vehicle, part)
    distance = 36,
    intensity = 0.75,
    dot = 0.96,
    xOffset = 0.5,
    yOffset = 2.0,
    focusing = 200,
}


NepHBO7.modDataPointers={} -- to hold vehicle mod data "pointers" to reduce API call


-- -----------------------------------------------------------------------------------------------------------
-- Utility

local function debugSay(message) 
    if NepHBO7.options.debugMode:getValue() then 
        print("NepHB: "..message)
    end
end

local function errorSay(message) 
    if NepHBO7.options.printErrors then
        print("NepHB: ERROR"..message)
    end
end

function NepHBO7.IsWreck (vehicle)
    if vehicle == nil then return nil end --should be nilprobably
    local isWreck = string.match(vehicle:getScript():getName(), "Burnt") or string.match(vehicle:getScript():getName(), "Smashed")
    return isWreck
end



-- to avoid huge numbers of function calls we're going to build a little vehicle modData collection
-- this will return the table in modData for our mod
-- uses keyID as an index.  If this somehow changes mid-game, no big deal - will just get the mod data again to the new value
NepHBO7.getModData = function (vehicle)
    if vehicle == nil then
        debugSay("getModData: vehicle is nil!")
        return nil
    end
    local keyID=vehicle:getKeyId()
    local retValue = nil
    
    if NepHBO7.modDataPointers[keyID] ~= nil then
        retValue = NepHBO7.modDataPointers[keyID]
    else
        local vModData = vehicle:getModData()
        if not vModData.NepHB then vModData.NepHB = {} end -- create empty table for our stuff if it does not exist
        NepHBO7.modDataPointers[keyID]=vModData.NepHB
        retValue = NepHBO7.modDataPointers[keyID]
        --debugSay("getModData: found modData for vehicle "..keyID)
    end
    if retValue == nil then
        debugSay("getModData: ERROR: failed to get or create moddata for vehicle!")
    end
    return retValue
end



-- -----------------------------------------------------------------------------------------------------------
-- Options



NepHBO7.initOptions = function()
	local options = PZAPI.ModOptions:create("NepHBJ", "High Beams")
    -- options:addTitle("High Beams")
    -- options:addDescription("Note: game must be restarted for options to take effect")
    
    if VehiclePart.NepVersion ~= nil then
        options:addDescription(getText("UI_options_NepHB_installYes"))
    else
        options:addDescription(getText("UI_options_NepHB_installNo1"))
        options:addDescription(getText("UI_options_NepHB_installNo2"))
    end
    options:addDescription("")
    NepHBO7.options.activationKey = options:addKeyBind("activationKey", getText("UI_options_NepHB_activationKey"), Keyboard.KEY_PERIOD, getText("UI_options_NepHB_activationKey_tooltip"))
    NepHBO7.options.alwaysOn = options:addTickBox("alwaysOn", getText("UI_options_NepHB_alwaysOn"), false, getText("UI_options_NepHB_alwaysOn_tooltip"))
    NepHBO7.options.lengthMult  =    options:addSlider("lengthMult",  getText("UI_options_NepHB_lengthMult"),    1, 3, 0.25, 1.5, getText("UI_options_NepHB_lengthMult_tooltip")) 
    NepHBO7.options.intensityMult  = options:addSlider("intensityMult",  getText("UI_options_NepHB_intensityMult"), 1, 2.5, 0.25, 2, getText("UI_options_NepHB_intensityMult_tooltip"))
    --NepHBO7.options.fixHeadlights =  options:addTickBox("fixHeadlights", getText("UI_options_NepHB_fixHeadlights"), false, getText("UI_options_NepHB_fixHeadlights_tooltip"))
    --NepHBO7.options.glowWhenHBOn  =  options:addTickBox("glowWhenHBOn", getText("UI_options_NepHB_glowWhenHBOn"),  false, getText("UI_options_NepHB_glowWhenHBOn_tooltip"))
    --NepHBO7.options.glowWhenHBOff =  options:addTickBox("glowWhenHBOff", getText("UI_options_NepHB_glowWhenHBOff"), false, getText("UI_options_NepHB_glowWhenHBOff_tooltip"))
    NepHBO7.options.radialMenu = options:addTickBox("radialMenu", getText("UI_options_NepHB_RadialMenu"), true, getText("UI_options_NepHB_RadialMenu_tooltip"))
	NepHBO7.options.debugMode = options:addTickBox("debugMode", getText("UI_options_NepHB_DebugMode"), true, getText("UI_options_NepHB_DebugMode_tooltip"))
    options:addDescription(getText("UI_options_NepHB_Info1"))

    debugSay("initOptions: options initilised")

end

NepHBO7.initOptions()




-- -----------------------------------------------------------------------------------------------------------
-- On, off and toggle

NepHBO7.activateHighBeams = function(vehicle)
    --debugSay("activateHighBeam: Start")
    if vehicle == nil then
        debugSay("activateHighBeam: vehicle is nil")
        return
    end
    local md = NepHBO7.getModData(vehicle)
    md.highBeamsOn = true
    NepHBO7.UpdateLights(vehicle)
end

NepHBO7.deactivateHighBeams = function(vehicle)
    --debugSay("deactivateHighBeam: Start")
    if vehicle == nil then
        debugSay("deactivateHighBeam: vehicle is nil")
        return
    end    
    local md = NepHBO7.getModData(vehicle)
    md.highBeamsOn = false
    NepHBO7.UpdateLights(vehicle)
end

NepHBO7.toggleHighBeam = function(vehicle)

    --debugSay("toggleHighBeam: Start")
    if vehicle == nil then
        debugSay("toggleHighBeam: vehicle is nil")
        return
    end    
    local md = NepHBO7.getModData(vehicle)
    if md == nil then return end;
    if md.highBeamsOn == true then  -- accounts for md being nil
        md.highBeamsOn=false 
    else 
        md.highBeamsOn=true             
    end 
    NepHBO7.UpdateLights(vehicle)
end


-- -----------------------------------------------------------------------------------------------------------
-- actually make stuff happen

NepHBO7.UpdateLights = function(vehicle)
    --debugSay("UpdateLights: Start")
    if vehicle == nil then
        debugSay("UpdateLights: vehicle is nil")
        return
    end    
    local md = NepHBO7.getModData(vehicle)
    if md == nil then return end;
    local HBOn = md.highBeamsOn
    if HBOn == nil then HBOn = false end
    local numHeadlightsUpdated = 0
    local distMult = 1
    local intensityMult = 1
    if HBOn then
        distMult = NepHBO7.options.lengthMult:getValue()
        intensityMult = NepHBO7.options.intensityMult:getValue()
    end
    if NepHBO7.options.alwaysOn:getValue() then HBOn = true end --force set to true     
    for partname,xOffsetMult in pairs(NepHBO7.headlightParts) do        
        local part = vehicle:getPartById(partname)
        if part ~= nil then
            part:createSpotLight((NepHBO7.vanilla.xOffset * xOffsetMult), NepHBO7.vanilla.yOffset,
            (NepHBO7.vanilla.distance * distMult), (NepHBO7.vanilla.intensity * intensityMult), NepHBO7.vanilla.dot,
            ZombRand(NepHBO7.vanilla.focusing))
            numHeadlightsUpdated=numHeadlightsUpdated+1
        end
    end

    --debugSay(string.format("UpdateLights: %d lights updated",numHeadlightsUpdated))
    if numHeadlightsUpdated == 0 then
        debugSay("UpdateLights: no lights were updated")
    end
end






function REFERENCEONLY_VehicleUtils_initHeadlight(vehicle, part)
	local item = VehicleUtils.createPartInventoryItem(part)
	local xOffset = 0.5
	local yOffset = 2.0
	local distance = 36
	local intensity = 0.75
	local dot = 0.96
	local focusing = ZombRand(200)
	-- NOTE: distance,intensity values vary between 50% and 100% of the given value based on part condition.
	-- NOTE: focusing value is ignored, instead it is set based on part condition.
    local params = part:getTable("headlight")
    if params then
        xOffset = tonumber(params.xOffset) or xOffset
        yOffset = tonumber(params.yOffset) or yOffset
        distance = tonumber(params.distance) or distance
        intensity = tonumber(params.intensity) or intensity
        dot = tonumber(params.dot) or dot
        focusing = tonumber(params.focusing) or focusing
    end
	if part:getId() == "HeadlightLeft" then
		part:createSpotLight(xOffset, yOffset, distance, intensity, dot, focusing)
	elseif part:getId() == "HeadlightRight" then
		part:createSpotLight(-xOffset, yOffset, distance, intensity, dot, focusing)
	end
end




















-- -----------------------------------------------------------------------------------------------------------
-- Events

-- press the button!
NepHBO7.onKeyPress = function (_keyPressed)
    if _keyPressed == NepHBO7.options.activationKey:getValue() then
        local v=getPlayer():getVehicle()
        if v then 
            NepHBO7.toggleHighBeam(v)
        end
    end
end

Events.OnKeyPressed.Add(NepHBO7.onKeyPress)



-- player got in, so update the lights
NepHBO7.OnEnterVehicle = function(player)
    
    local v=player:getVehicle()
    if v then
        NepHBO7.UpdateLights(v)
    end
end
Events.OnEnterVehicle.Add(NepHBO7.OnEnterVehicle)

-- did we load a game where player was already in a vehicle?
NepHBO7.OnCreatePlayer = function(playerNum, player) 
    local v=player:getVehicle()
    if v then
        NepHBO7.UpdateLights(v)
    end
end
Events.OnCreatePlayer.Add(NepHBO7.OnCreatePlayer)

-- Update lighst when a vhicle is spawned, which seems to include Reloading, walking back into cell range, and setAngle.  
NepHBO7.setHeadlightsOnSpawn = function(vehicle)
    if NepHBO7.IsWreck(vehicle) then return end --avoids errors from trying to mess wit lights on a wreck
    NepHBO7.UpdateLights(vehicle)
end
Events.OnSpawnVehicleEnd.Add(NepHBO7.setHeadlightsOnSpawn)



-- -----------------------------------------------------------------------------------------------------------
-- UI stuff


--  Set headlight icon color on dashboard
ISVehicleDashboard.NepOG_prerender = ISVehicleDashboard.prerender
function ISVehicleDashboard:prerender()
	
	ISVehicleDashboard.NepOG_prerender(self)

	if not self.vehicle or not ISUIHandler.allUIVisible then return end  -- don't run if not in a vehicle or UI is off... otherwise throws an error when getting out of a vehicle when it excutes one final time.
	local alpha = self:getAlphaFlick(0.65); -- flickering from crashes etc
	local hlOn = self.vehicle:getHeadlightsOn()
    local md = NepHBO7.getModData(self.vehicle)
    if md == nil then return end;
    if hlOn and md.highBeamsOn then
        self.lightsTex.backgroundColor = {r=0.2, g=0.3, b=1,a=alpha} -- I tried to set this color in options and it hates me.
    end
end

-- Add high Beams to Radial Menu

ISVehicleMenu.NepOG_showRadialMenu = ISVehicleMenu.showRadialMenu
function ISVehicleMenu.showRadialMenu(player)
	ISVehicleMenu.NepOG_showRadialMenu(player);
    if not NepHBO7.options.radialMenu:getValue() then return end;
	local vehicle = player:getVehicle();
	if not vehicle then return end;
    local md = NepHBO7.getModData(vehicle)
    if md == nil then return end;
    local icon = NepHBO7.options.radialTextureOn
    local text = getText("ContextMenu_HighBeamsTurnOn")
    if md.highBeamsOn then 
        icon = NepHBO7.options.radialTextureOff 
        text = getText("ContextMenu_HighBeamsTurnOff")
    end
	local menu = getPlayerRadialMenu(player:getPlayerNum());
	menu:addSlice(text, icon, NepHBO7.toggleHighBeam, vehicle)

end



print("NepHB: High Beams 3.0: Main Script Loading Complete.")

