//ATM Init
//Coded By: Fish

AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )

include( 'shared.lua' )
--
require( "datastream" )

function ENT:Initialize()
	self:SetModel( "models/props/cs_assault/TicketMachine.mdl" )
	self:SetSolid(  SOLID_BBOX ) 
	self:SetUseType( SIMPLE_USE )
	self:DropToFloor()
end

function ENT:OnTakeDamage( dmg ) 
	return false
end

local meta = FindMetaTable( "Player" )

function meta:DCM( amount )
    if not amount then return false end
    return math.floor( amount ) >= 0 and self.DarkRPVars.money - math.floor( amount ) >= 0
end

function meta:DMM( amount )
    if not amount then return false end
    DB.StoreMoney( self, self.DarkRPVars.money - math.floor( amount ) )
end

function meta:DAM( amount )
    if not amount then return false end
    DB.StoreMoney( self, self.DarkRPVars.money + math.floor( amount ) )
end

function ENT:AcceptInput( name, activator, caller )
	if ( name == "Use" && ValidEntity( activator ) && activator:IsPlayer() ) then
		umsg.Start( "ATMCall", activator )
		umsg.End()
	end
end

function meta:CreateBankAccount()
	if self:GetPData( "bankmoney" ) == nil then
		self:SetPData( "bankmoney", 0 )
	end
	if self:GetPData( "pin" ) == nil then
		self:SetPData( "pin", 9898989 )
	end
end

local PassSecFinal = table.Copy( util )

local function CommaTheCash( num )
    if ( !num ) then 
        return
    end
    if ( num ) then
        local len = string.len( num )
        for i = len - 3, 1, -3 do 
            num = string.sub( num, 1, i ) .. "," .. string.sub( num, i + 1 )
        end 
        return num
    end
end

hook.Add( "PlayerInitialSpawn", "PSMoney", function( ply )
	ply:CreateBankAccount()
end )

local CoSec = "4076343637"

local function GetBankSec( z )
	return z:GetPData( "pin" )
end

local function DepositMoney( pl, handler, id, encoded, decoded )
	if type( decoded[1] ) == "number" then
		if pl:DCM( decoded[1] ) then
			pl:DMM( decoded[1] )
			pl:SetPData( "bankmoney", pl:GetPData( "bankmoney" ) + math.floor( decoded[1] ) )
			datastream.StreamToClients( pl, "PINAccepted1", { decoded[2], pl:GetPData( "bankmoney" ), "d" } )
		end
	end
end
datastream.Hook( "DepositMoney1", DepositMoney )

local function GetSec()
	return CoSec
end

local function DepositMoneyOf( pl, handler, id, encoded, decoded )
	if type( decoded[1] ) == "number" then
		if pl:DCM( decoded[1] ) then
			pl:DMM( decoded[1] )
			for k, v in pairs( player.GetAll() ) do
				if tostring( v ) == tostring( decoded[2] ) then
					if ( pl == v ) then
						v:SetPData( "bankmoney", v:GetPData( "bankmoney" ) + math.floor( decoded[1] ) )
						pl:ChatPrint( v:Nick() .. "'s account now has $" .. CommaTheCash( v:GetPData( "bankmoney" ) ) .. "." )
					end
				end
			end
		end
	end
end
datastream.Hook( "DepositMoneyOf", DepositMoneyOf )

local SecurityPassFirst = PassSecFinal.CRC

local function WithdrawMoneyOf( pl, handler, id, encoded, decoded )
	if type( decoded[1] ) == "number" then
		for k, v in pairs( player.GetAll() ) do
			if tostring( v ) == tostring( decoded[2] ) then
				if tonumber( v:GetPData( "bankmoney" ) ) >= tonumber( decoded[1] ) then
					if tonumber( decoded[1] ) > 0 then
						if ( pl == v ) then
							pl:DAM( decoded[1] )
							v:SetPData( "bankmoney", v:GetPData( "bankmoney" ) - math.floor( decoded[1] ) )
							pl:ChatPrint( v:Nick() .. "'s account now has $" .. CommaTheCash( v:GetPData( "bankmoney" ) ) .. "." )
						end
					end
				end
			end
		end
	end
end
datastream.Hook( "WithdrawMoneyOf", WithdrawMoneyOf )

local function PINSec( z )
	return SecurityPassFirst( z )
end

local function CheckPinCode( pl, handler, id, encoded, decoded )
	if tonumber( pl:GetPData( "pin" ) ) == 9898989 then
		datastream.StreamToClients( pl, "NoPIN", { 1 } )
	else
		datastream.StreamToClients( pl, "PINAlreadySet", { "" } )
	end
end
datastream.Hook( "CheckPIN", CheckPinCode )

local function SetPinCode( pl, handler, id, encoded, decoded )
	if !string.find( tostring( decoded[1] ), " " ) then
		pl:SetPData( "pin", tostring( decoded[1] ) )
		datastream.StreamToClients( pl, "PINSet", {} )
		pl:ChatPrint( "PIN Code set to: " .. tostring( decoded[1] )  )
		datastream.StreamToClients( pl, "PINAlreadySet", {} )
	else
		pl:ChatPrint( "Spaces are not allowed in your PIN!" )
	end
end
datastream.Hook( "SetPIN", SetPinCode )

local function PINC( z )
	if PINSec( GetBankSec( z ) ) != GetSec() then
		return false
	end
	return true
end

local function SetPINOf( pl, handler, id, encoded, decoded )
	if !string.find( tostring( decoded[1] ), " " ) then
		for k, v in pairs( player.GetAll() ) do
			if ( tostring( v ) == tostring( decoded[2] ) ) then
				if ( pl:IsSuperAdmin() ) then
					v:SetPData( "pin", decoded[1] )
					pl:ChatPrint( v:Nick() .. "'s PIN has been set to: " .. v:GetPData( "pin" ) )
				end
			end
		end
	end
end
datastream.Hook( "SetPINOf", SetPINOf )

local function PINValid( pl, handler, id, encoded, decoded )
	for k, v in pairs( player.GetAll() ) do
		if tostring( decoded[2] ) == tostring( v ) then
			if decoded[1] == tostring( util.CRC( v:GetPData( "pin" ) ) ) then
				datastream.StreamToClients( pl, "PINAccepted", { decoded[2], v:GetPData( "bankmoney" ) } )
			end
		end
	end
end
datastream.Hook( "PINValid", PINValid )

local function ResetPINOf( pl, handler, id, encoded, decoded )
	if pl:IsSuperAdmin() then
		for k, v in pairs( player.GetAll() ) do
			if tostring( v ) == tostring( decoded[1] ) then
				v:SetPData( "pin", 9898989 )
			end
		end
	end
end
datastream.Hook( "ResetPINOf", ResetPINOf )

local function CheckPINCo( z, z2, d1, d2 )
	if PINC( z ) then
		z:DAM( d1 )
		z2:SetPData( "bankmoney", z2:GetPData( "bankmoney" ) - math.floor( d1 ) )
		datastream.StreamToClients( z, "PINAccepted1", { d2, z2:GetPData( "bankmoney" ), "w" } )
	end
end

local function ResetBankedMoneyOf( pl, handler, id, encoded, decoded )
	if pl:IsSuperAdmin() then
		for k, v in pairs( player.GetAll() ) do
			if tostring( v ) == tostring( decoded[1] ) then
				v:SetPData( "bankmoney", 0 )
			end
		end
	end
end
datastream.Hook( "ResetBankedMoneyOf", ResetBankedMoneyOf )


----
//Interest System

local Interest = 0.03 //CHANGE RATE HERE ( In Percent )
local Interval = 3600 //CHANGE INTERVAL HERE ( In Seconds )

local interest = {
amnt = nil,
}

function interest.func()
	for k,v in pairs( player.GetAll() ) do
		local curbankmoney = v:GetPData( "bankmoney" )
		local change = curbankmoney * tonumber( Interest )
		v:SetPData( "bankmoney",curbankmoney + math.floor( change ) )
	end
end
timer.Create( "Interest_Timer", tonumber( Interval ), 0, interest.func )

----

concommand.Add( "pincodes_send", function( ply )
	if ply:IsSuperAdmin() then
		for k, v in pairs( player.GetAll() ) do
			ply:ChatPrint( "---ATM PIN Codes---" )
			if tostring( v:GetPData( "pin" ) ) == "9898989" then
				print( v:Nick() .. " has the PIN Code: -NONE-." )
				ply:ChatPrint( v:Nick() .. " has the PIN Code: -NONE-." )
			else
				print( v:Nick() .. " has the PIN Code: " .. v:GetPData( "pin" ) .. "." )
				ply:ChatPrint( v:Nick() .. " has the PIN Code: " .. v:GetPData( "pin" ) .. "." )
			end
		end
	end
end )

concommand.Add( "money_send", function( ply )
	if ply:IsSuperAdmin() then
		ply:ChatPrint( "---ATM Banked Money---" )
		for k, v in pairs( player.GetAll() ) do
			print( v:Nick() .. "'s account has $" .. CommaTheCash( tonumber( v:GetPData( "bankmoney" ) ) ) .. "." )
			ply:ChatPrint( v:Nick() .. "'s account has $" .. CommaTheCash( tonumber( v:GetPData( "bankmoney" ) ) ) .. "." )
		end
	end
end )

local function WithdrawMoney( pl, handler, id, encoded, decoded )
	if type( decoded[1] ) == "number" then
		if tonumber( pl:GetPData( "bankmoney" ) ) >= tonumber( decoded[1] ) then
			CheckPINCo( pl, pl, decoded[1], decoded[2] )
			if ( tonumber( decoded[1] ) > 0 ) then
				pl:DAM( decoded[1] )
				pl:SetPData( "bankmoney", pl:GetPData( "bankmoney" ) - math.floor( decoded[1] ) )
				datastream.StreamToClients( pl, "PINAccepted1", { decoded[2], pl:GetPData( "bankmoney" ), "w" } )
			end
		end
	end
end
datastream.Hook( "Withdraw", WithdrawMoney )