-- =============================================================================
-- Setup constants.
-- =============================================================================
require("zxcmodule")
local ViolLua = { }

ViolLua.Colors = { 
    [ 'Main' ]       = Color( 179, 156, 149 ), 

    [ 'White' ]     = Color( 255, 255, 255 ),
    [ 'Black' ]     = Color( 0, 0, 0 ),
    [ 'Gray' ]      = Color( 30, 30, 30 ),
    [ 'Invisible' ] = Color( 0, 0, 0, 0 ),

    [ 'Light Gray' ] = Color( 80, 80, 80 ),
    [ 'Dark Gray' ]  = Color( 18, 18, 18 ),
    [ 'Cyan' ]       = Color( 60, 180, 225 ),
    [ 'Purple' ]     = Color( 133, 97, 136 ),

    [ 'Red' ]   = Color( 255, 0, 0 ),
    [ 'Green' ] = Color( 0, 255, 0 ),
    [ 'Blue' ]  = Color( 0, 0, 255 )
}

ViolLua.Localplayer = LocalPlayer( )

ViolLua.Resolution = {
    Height = ScrH( ),
    Width  = ScrW( )
}

ViolLua.Gamemode = engine.ActiveGamemode( )

ViolLua.Config = { }

-- =============================================================================
-- Setup utility functions.
-- =============================================================================

function ViolLua:Print( isError, Text, ... )
    local Prefix = isError and '[ ERROR ]' or '[ ViolLua ]'
    local Color  = isError and self.Colors[ 'Red' ] or self.Colors[ 'Main' ]

    MsgC( Color, Prefix, ' ', self.Colors[ 'White' ], string.format( Text, ... ), '\n' )
end

-- =============================================================================
-- Setup environment.
-- =============================================================================

ViolLua:Print( false, 'Setting up environment...' )

ViolLua._G = table.Copy( _G )

ViolLua.Environment = setmetatable( {
    _G  = ViolLua._G,
    __G = _G,

    ViolLua = ViolLua
}, {
    __index = ViolLua._G
} )

function ViolLua:Load( Code, Environment, ... )
    local Function = CompileString( Code, 'ViolLua' )   

    if ( not Function ) then 
        return self:Print( true, 'Failed to compile code! (%s, %s)', string.NiceSize( #Code ), util.CRC( Code ) )
    end

    if ( Environment ) then 
        Function = setfenv( Function, Environment )
    end

    return true, Function( ... )
end

function ViolLua:LoadFile( Directory, Insecure )
    local Handle = file.Open( Directory, 'rb', 'GAME' )

    if ( not Handle ) then 
        return self:Print( true, 'Failed to open handle to file %s!', string.GetFileFromFilename( Directory ) )
    end

    local Valid, Data = self:Load( Handle:Read( Handle:Size( ) ), not Insecure and self.Environment or nil )

    if ( Valid ) then 
        ViolLua:Print( false, 'Successfully loaded file %s!', Directory )
    else 
        ViolLua:Print( false, 'Failed loaded file %s!', Directory )
    end

    Handle:Close( )

    return Data
end

function ViolLua:LoadDirectory( Directory, Insecure )
    local Files = file.Find( Directory .. '*.lua', 'GAME' )

    for i = 1, #Files do
        self:LoadFile( Directory .. Files[ i ], Insecure )
    end
end

-- =============================================================================
-- Load libraries.
-- =============================================================================

ViolLua:Print( false, 'Loading libraries...' )

if ( not ViolLua:LoadFile( 'lua/ViolLua/libraries/cpp/modmgr.lua' ) ) then 
    return 
end

ViolLua:LoadFile( 'lua/ViolLua/libraries/external/random.lua' )

ViolLua:LoadFile( 'lua/ViolLua/libraries/render/materials.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/render/beams.lua' )

ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/engine.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/hitboxes.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/enum.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/hookmgr.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/items.lua' )

ViolLua:LoadFile( 'lua/ViolLua/libraries/render/overlay.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/render/hitmarker.lua' )

ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/fullupdate.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/optimizations.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/client.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/records.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/notify.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/shots.lua' )
ViolLua:LoadFile( 'lua/ViolLua/libraries/sdk/createmove.lua' )

ViolLua:LoadFile( 'lua/ViolLua/libraries/render/csent.lua' )

ViolLua:LoadFile( 'lua/ViolLua/libraries/gamemodes/handler.lua' )

-- =============================================================================
-- Load modules.
-- =============================================================================

ViolLua:Print( false, 'Loading modules...' )

ViolLua:LoadFile( 'lua/ViolLua/modules/menu/menu.lua' )
ViolLua:LoadFile( 'lua/ViolLua/modules/menu/form.lua' )

ViolLua:LoadFile( 'lua/ViolLua/modules/ragebot/main.lua' )

ViolLua:LoadFile( 'lua/ViolLua/modules/visuals/main.lua' )

ViolLua:LoadFile( 'lua/ViolLua/modules/miscellaneous/main.lua' )

-- =============================================================================
-- Gather dynamic files.
-- =============================================================================

ViolLua:Print( false, 'Gathering dynamic files...' )

ViolLua:LoadDirectory( 'ViolLua/safe/', false )
ViolLua:LoadDirectory( 'ViolLua/unsafe/', true )