Global.C_DBPaths = Global.C_DBPaths or FileIO:ReadScriptDataFrom(Path:Combine(Corruptor.ModPath, "Data", "Paths.bin"), "binary")

function Corruptor:Init()
    Corruptor.random_textures = {}
    Corruptor.spam_stop = {}
    Corruptor.random_num = Corruptor.Options:GetValue("TextureCount")
    local randomize_textures = Corruptor.Options:GetValue("RandomizeTextures")
    local randomize_animations = Corruptor.Options:GetValue("RandomizeAnimations")
    local randomize_sounds = Corruptor.Options:GetValue("RandomizeSounds")
    local randomize_spawned_rot = Corruptor.Options:GetValue("RandomizeSpawnedRotation")
    local rot_offset = Corruptor.Options:GetValue("RandomizeSpawnedRotationOffset")
    for i=1, Corruptor.random_num do
        local rnd = table.random_key(Global.C_DBPaths.texture)
        table.insert(Corruptor.random_textures, rnd:id())
    end

    if randomize_textures then
        local MassUnit = getmetatable(MassUnitManager)
        local Wrld = getmetatable(World)
        local App = getmetatable(Application)
        local mat_ids = Idstring("material")
        local diffuse_ids = Idstring("diffuse_texture")
        local normal_ids = Idstring("normal")
        local done = {}
    
        Wrld._orig_spawn_unit = Wrld._orig_spawn_unit or Wrld.spawn_unit
        MassUnit._orig_spawn_unit = MassUnit._orig_spawn_unit or MassUnit.spawn_unit
        
        App.set_material_texture_corrupt = App.set_material_texture_corrupt or App.set_material_texture
        function App:set_material_texture() end
    
        local function spawn_unit(self, unit, pos, rot, ...)
            if rot and randomize_spawned_rot then
                rot = Rotation(rot:yaw() + math.random(-rot_offset, rot_offset), rot:pitch() + math.random(-rot_offset, rot_offset), rot:roll() + math.random(-rot_offset, rot_offset))
            end
            local unit = self:_orig_spawn_unit(unit, pos, rot, ...)
            if not done[unit:name():key()] then
                done[unit:name():key()] = true
                for _, material in pairs(unit:get_objects_by_type(mat_ids)) do
                    Application:set_material_texture_corrupt(material, diffuse_ids, Corruptor:GetRandomTexture(), normal_ids)
                end
            end
            return unit
        end
    
        Wrld.spawn_unit = spawn_unit
        MassUnit.spawn_unit = spawn_unit
    
        local ws_panel = Overlay:gui():create_scaled_screen_workspace(10, 10, 10, 10, 10):panel()
        local Panel = getmetatable(ws_panel:panel())
        local Bitmap = getmetatable(ws_panel:bitmap({w = 0}))
        Overlay:newgui():destroy_workspace(ws_panel)
    
        Panel._orig_bitmap = Panel._orig_bitmap or Panel.bitmap
        local not_allowed = {
            ["guis/textures/mouse_pointer"] = true,
            ["guis/textures/pd2/hud_corner"] = true,
            ["guis/textures/menu_tickbox"] = true
        }
        function Panel:bitmap(params, ...)
            local tex = params.texture
            if not not_allowed[tex] then
                params.texture = Corruptor:GetRandomTexture()
            end
            return self:_orig_bitmap(params, ...)
        end
    
        Bitmap._orig_set_image = Bitmap._orig_set_image or Bitmap.set_image
        function Bitmap:set_image(tex, ...)
            if not not_allowed[tex] then
                tex = Corruptor:GetRandomTexture()
            end
            self:_orig_set_image(tex, ...)
        end
    
        Panel._orig_video = Panel._orig_video or Panel.video
        function Panel:video(params, ...)
            params.video = table.random_key(Global.C_DBPaths.movie)
            return self:_orig_video(params, ...)
        end
    end
end

function Corruptor:GetRandomSound(dallas)
    if dallas and not table.contains(Global.stored_sound_ids, dallas) then
        table.insert(Global.stored_sound_ids, dallas)
    end
    return Global.stored_sound_ids[math.random(1, #Global.stored_sound_ids)]
end

function Corruptor:GetRandomTexture()
    return Corruptor.random_textures[math.random(1, Corruptor.random_num)]
end

Hooks:Add("MenuManagerSetupCustomMenus", "lol", function(self, nodes)
    local randomize_set_rot = Corruptor.Options:GetValue("RandomizeSetRot")
    local randomize_anim_speed = Corruptor.Options:GetValue("RandomizeAnimSpeed")
    local rot_offset = Corruptor.Options:GetValue("RandomizeSetRotOffset")

    if Unit and randomize_set_rot then
        local _set_rotation = _set_rotation or Unit.set_rotation
        function Unit:set_rotation(rot)
            _set_rotation(self, Rotation(rot:yaw() + math.random(-rot_offset, rot_offset), rot:pitch() + math.random(-rot_offset, rot_offset), rot:roll() + math.random(-rot_offset, rot_offset)))
        end
    end

    if randomize_anim_speed and StateMachineInstance then
        local _set_speed = _set_speed or StateMachineInstance.set_speed
        function StateMachineInstance:set_speed(state, speed, ...)
            return _set_speed(self, state, math.random(1, 50))
        end
    end

    local hold_anims = {}
    local animations = {}
    if randomize_sounds then
        for _, weapon in pairs(tweak_data.weapon) do
            if weapon.sounds then
                for sound in pairs(weapon.sounds) do
                    if sound ~= "prefix" then
                        weapon.sounds[sound] = Corruptor:GetRandomSound()
                    end
                end
            end
            table.insert(hold_anims, weapon.weapon_hold)
            table.insert(animations, weapon.animations)
        end
    end
    if randomize_animations then
        for _, weapon in pairs(tweak_data.weapon) do
            weapon.animations = animations[math.random(1, #animations)]
            weapon.weapon_hold = hold_anims[math.random(1, #hold_anims)]
        end
    end
end)

BeardLib:AddUpdater("lol", function(t, dt) 
    if not Corruptor._next_pee or t >= Corruptor._next_pee then
        SoundDevice:set_rtpc("game_speed", math.random(0.01, 2))
        Corruptor._next_pee = t + 2
    end
end, true)

local REPLACED_FUCKER
Hooks:Add("GameSetupUpdate", "lol", function(t, dt)
    if random_textures and not REPLACED_FUCKER and Underlay:loaded() then
        local material = Underlay:material(Idstring("sky"))
        if material then
            Application:set_material_texture_corrupt(material, diffuse_ids, Corruptor:GetRandomTexture(), normal_ids)
            REPLACED_FUCKER = true
        end
    end
    if randomize_sounds then
        for sound, spam in pairs(Corruptor.spam_stop) do
            if spam <= t then
                if alive(sound._unit) then
                    sound:stop()
                end
                Corruptor.spam_stop[sound] = nil
            end
        end
    end
end)