-- if not CLIENT then return end

prettyjson = require "pretty.json"

function tableMerge(t1, t2)
    for k,v in pairs(t2) do
        if type(v) == "table" then
            if type(t1[k] or false) == "table" then
                tableMerge(t1[k] or {}, t2[k] or {})
            else
                t1[k] = v
            end
        else
            t1[k] = v
        end
    end
    return t1
end

function dump(o)
    if type(o) == 'table' then
       local s = '{ '
       for k,v in pairs(o) do
          if type(k) ~= 'number' then k = '"'..k..'"' end
          s = s .. '['..k..'] = ' .. dump(v) .. ','
       end
       return s .. '} '
    else
       return tostring(o)
    end
end

local settings = {
    ModEnabled = true,
    version = "1.5.1",
    SaveSettings = true,
    RedLuminosityMultiplier=1,
    GreenLuminosityMultiplier=1,
    BlueLuminosityMultiplier=1,
    GlobalLuminosityMultiplier=900, -- random constant 
    LuminosityOfItems = {
        lamp=1,
        lightfluorescentm01=1,
        lightfluorescentm02=1,
        lightfluorescentm03=1,
        lightfluorescentm04=1,
        lightfluorescentl01=2,
        lightfluorescentl02=2,
        lighthalogenmm01=1,
        lighthalogenmm02=1,
        lighthalogenmm03=1,
        lighthalogenm04=1,
        lightleds01=1,
        op_workbenchlamp= 1,
        emergencylight= 0.2,
        lightcomponent= 0.05,
        lightcomponent90= 0.05,
        lightcomponentround= 0.05
    },
    cursed={
        makeOutsideLightsShadowCasting = false,
        makeOutsideLightsDrawnBehindSub = false,
        makeInsideLightsShadowCasting = false,
        makeInsideLightsDrawnInFrontOfSub = false,
        turnAllOutsideLightsOn=false,
        turnAllOutsideLightsOff=false,
    }
}

local modFolder = ...

function saveSettings()
    if settings.SaveSettings then
        File.Write(modFolder .. "/settings.json", prettyjson.stringify(settings, nil, 4)) -- yay
    end
end

function loadSettings()
    if File.Exists(modFolder .. "/settings.json") then
        return json.parse(File.Read(modFolder .. "/settings.json"))
    end
end

function migrateSettings(oldSettings)
    local version = settings.version

    tableMerge(settings,oldSettings)

    settings.version = version
end

function recalculateRange(light)
    if not settings.ModEnabled then return end
    local luminosityMult = settings.LuminosityOfItems[light.Item.Prefab.Identifier.Value]

    if luminosityMult == nil then return end

    if settings.cursed.makeOutsideLightsShadowCasting then
        if light.Item.CurrentHull == nil then
            if not light.DrawBehindSubs and not light.CastShadows then  
                light.CastShadows = true
            end
        end
    end

    if settings.cursed.makeOutsideLightsDrawnBehindSub then
        if light.Item.CurrentHull == nil then
            if not light.DrawBehindSubs and not light.CastShadows then  
                light.DrawBehindSubs = true
            end
        end
    end

    if settings.cursed.makeInsideLightsShadowCasting then
        if light.Item.CurrentHull ~= nil then
            if not light.DrawBehindSubs and not light.CastShadows then  
                light.CastShadows = true
            end
        end
    end

    if settings.cursed.makeInsideLightsDrawnInFrontOfSub then
        if light.Item.CurrentHull ~= nil then
            light.DrawBehindSubs = false
        end
    end

    if settings.cursed.turnAllOutsideLightsOn then 
        if light.Item.CurrentHull == nil then
            light.IsOn = true
        end
    end

    if settings.cursed.turnAllOutsideLightsOff then 
        if light.Item.CurrentHull == nil then
            light.IsOn = false
        end
    end

    local l = light.LightColor.R*settings.RedLuminosityMultiplier + light.LightColor.G *settings.GreenLuminosityMultiplier + light.LightColor.B *settings.BlueLuminosityMultiplier
    l = l / 255 / 3
    l = l * light.LightColor.A / 255
    l = l * luminosityMult 

    light.Range = math.sqrt(l) * settings.GlobalLuminosityMultiplier
end

function globalRecalc()
    for k, v in pairs(Item.ItemList) do
        local light -- omg lua

        if settings.LuminosityOfItems[v.Prefab.Identifier.Value] == nil then goto continue end

        light = v.GetComponentString("LightComponent")
        if light == nil then goto continue end

        recalculateRange(light)

        ::continue:: -- omg lua
    end
end

Game.AddCommand('lightrange', 'toggles recalculation of light ranges', function()
    settings.ModEnabled = not settings.ModEnabled

    if settings.ModEnabled then print('----------------------- On -----------------------' ) end
    if not settings.ModEnabled then print('----------------------- Off -----------------------' ) end

    saveSettings()
end, nil, false)

Hook.Patch("Barotrauma.Items.Components.LightComponent", "set_LightColor", function(instance, ptable)
    if instance.Item.Submarine ~= nil and not instance.Item.Submarine.Loading then
        recalculateRange(instance)
    end
end, Hook.HookMethodType.After)

Game.AddCommand('recalclightranges', 'forces recalculation of light ranges', function()
    local newSettings = loadSettings()
    if newSettings ~= nil then settings = newSettings end

    globalRecalc()
end, nil, false)

-- Hook.Add("roundStart", "recalculate light ranges", function()
--     globalRecalc()
-- end)

-- round start, sub/shuttle spawn, switch in sub editor
Hook.Patch("Barotrauma.Submarine", ".ctor", function(instance, ptable)
    globalRecalc()
end, Hook.HookMethodType.After)


if not File.Exists(modFolder .. "/settings.json") then
    saveSettings()
else
    local newSettings = loadSettings()

    if newSettings.version == nil or newSettings.version ~= settings.version then
        migrateSettings(newSettings)
        saveSettings()
    else 
        settings = newSettings
    end
end

-- after cl_reloadlua
-- first call before round start has no effect because item list doesn't exist yet
globalRecalc()












