local mysql = exports.mysql
local loadedVehicle = {}
enginelessVehicle = { [510]=true, [509]=true, [481]=true }
_createVehicle = createVehicle
function createVehicle(model, x, y, z, rx, ry, rz)
	local veh = _createVehicle(model, x, y, z, rx, ry, rz)
	if getRandomPlayer() then
		triggerClientEvent(root, "onClientVehicleCreate", root, veh)
	end
	return veh
end
function loadAllVehicle()
	local connectionParams = exports.mysql:getConnectionParams()
	newsql = dbConnect("mysql",connectionParams[1],connectionParams[2],connectionParams[3],connectionParams[4],connectionParams[5])
	if not newsql then
		outputDebugString("Error")
		return
	end
	
	dbQuery(function(qh)
		local res, rows, errorMsg = dbPoll(qh, 0)
		if rows > 0 then
			for k,v in pairs(res) do
				loadOneVehicle(res[k])
			end
		end
	end, newsql, "SELECT * FROM cars")
end
addEventHandler("onResourceStart", resourceRoot, loadAllVehicle)
local savedTuning = {}
function saveTuning(veh, savedUpdate)
	if savedUpdate then
		if savedTuning[veh] then
			return
		end
		savedTuning[veh] = true
	end
	local json = {}
	for i=0,16 do
		local upgrade = tonumber(getElementData(veh, "veh:Upgrade"..i)) or 0
		json[i] = upgrade
	end
		
	local json2 = {}
	for i=1,4 do
		local level = tonumber(getElementData(veh, "veh:Level"..i)) or 0
		json2[i] = level
	end
	local airRide = getElementData(veh, "veh:AirRide")
	if airRide then
		airRide = 1
	else
		airRide = 0
	end
		
	local doorID = getElementData(veh, "vDoorType") and 1 or 0
	local chip = getElementData(veh, "veh:Chip")
	if chip then
		chip = 1
	else
		chip = 0
	end
	local neonID = tonumber(getElementData(veh, "veh:Neon")) or 0
	local id = tonumber(getElementData(veh, "dbid")) or 0
	if id > 0 then
		dbExec(newsql, "UPDATE cars SET door = ?, neon = ?, airRide = ?, levels = ?, upgrades = ?, chip = ? WHERE id = ?", doorID, neonID, airRide, toJSON({json2[1],json2[2],json2[3],json2[4]}), toJSON({json[1],json[2],json[3],json[4],json[5],json[6],json[7],json[8],json[9],json[10],json[11],json[12],json[13],json[14],json[15],json[16]}), chip, id)
	end
end
addEvent("saveTuning", true)
addEventHandler("saveTuning", root, saveTuning)
addEventHandler("onResourceStart", root, function(resource)
	if getResourceName(resource) == "ex_tuning" then
		savedTuning = {}
	end
end)
addEventHandler("onResourceStop", root, function(resource)
	if getResourceName(resource) == "ex_tuning" then
		for k,veh in ipairs(getElementsByType("vehicle")) do
			exports.vehicle:saveTuning(veh, true)
		end
	end
end)
function saveOneVehicle(v, pos)
	if not newsql then return end
	local id = tonumber(getElementData(v, "dbid")) or -1
	if id > 0 then
		local int = getElementInterior(v)
		local dim = getElementDimension(v)
		if pos then
			local x,y,z = getElementPosition(v)
			local rx,ry,rz = getElementRotation(v)
			setElementData(v, "veh:Int", int)
			setElementData(v, "veh:Dim", dim)
			
			setVehicleRespawnPosition(v, x,y,z,rx,ry,rz)
			
			dbExec(newsql, "UPDATE cars SET interior = ?, dimension = ?, x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ? WHERE id = ?", int, dim, x, y, z, rx, ry, rz, id)
			return
		end
		local boxArray = {}
		for i=1,4 do
			boxArray[#boxArray+1] = getElementData(v, "box_object"..i) or -1
		end
		local boxs = toJSON(boxArray)
		local health = getElementHealth(v)
		local r,g,b,r1,g1,b1 = getVehicleColor(v, true)
		local r2,g2,b2 = getVehicleHeadLightColor(v)
		local owner = tonumber(getElementData(v, "veh:Owner")) or -1
		local fuel = tonumber(getElementData(v, "veh:FuelData")) or -1
		local locked = tonumber(getElementData(v, "veh:Locked")) or 1
		local handbrake = tonumber(getElementData(v, "handbrake")) or 1
		local carshop_id = tonumber(getElementData(v, "veh:CarshopID")) or 0
		local carshop_pos = tonumber(getElementData(v, "veh:CarshopPos")) or 0
		local carshop_price = tonumber(getElementData(v, "veh:Price")) or 0
		local pj = tonumber(getElementData(v, "veh:PaintJob")) or 0
		local model = getElementModel(v)
		if owner ~= -1 then
			saveTuning(v)
			dbExec(newsql, "UPDATE cars SET plate = ?, handbrake = ?, locked = ?, r1 = ?, g1 = ?, b1 = ?, model = ?, health = ?, owner = ?, fuel = ?, boxs = ?, pj = ? WHERE id = ?", getVehiclePlateText(v), handbrake, locked, r1, g1, b1, model, health, owner, fuel, boxs, pj, id)
		end
	end
end
addEventHandler("onResourceStop", resourceRoot, function()
	for k,v in ipairs(getElementsByType("vehicle")) do
		saveOneVehicle(v)
	end
end)
addEvent("onServerVehicleLightsStateChange", true)
addEventHandler("onServerVehicleLightsStateChange", getRootElement(), function(v,s)
	setVehicleOverrideLights(v,s)
end)
addEvent("onClientParkVehicle", true)
addEventHandler("onClientParkVehicle", root, function(veh)
	saveOneVehicle(veh, true)
end)
local getPlayerName = function(p)
	return string.gsub(tostring(p:getData("char:Name")), " ", "_")
end
function loadOneVehicle(data, shop)
	local id = tonumber(data["id"]) or 0
	if id > 0 then
		loadedVehicle[id] = createVehicle(data["model"], data["x"], data["y"], data["z"], data["rx"], data["ry"], data["rz"])
		if loadedVehicle[id] then
			setVehicleVariant(loadedVehicle[id], data["var1"], data["var2"])
			setVehicleRespawnPosition(loadedVehicle[id], data["x"], data["y"], data["z"], data["rx"], data["ry"], data["rz"])
			setElementID(loadedVehicle[id], "veh:"..id)
			setElementData(loadedVehicle[id], "dbid", id)
			setElementData(loadedVehicle[id], "veh:Owner", data["owner"])
			setElementData(loadedVehicle[id], "veh:FuelData", data["fuel"])
			setElementData(loadedVehicle[id], "veh:Engine", 0)
			setElementData(loadedVehicle[id], "veh:Lights", 0)
			setElementData(loadedVehicle[id], "veh:Faction", data["faction"])
			setElementData(loadedVehicle[id], "veh:Locked", data["locked"])
			
			local boxs = fromJSON(data["boxs"])
			for i=1,4 do
				if(boxs[i])then
					setElementData(loadedVehicle[id], "box_object"..i, tonumber(boxs[i] or -1))
				end
			end
			
			if data["locked"] == 1 and data["owner"] > 0 then
				setVehicleLocked(loadedVehicle[id], true)
			end
			
			if data["airRide"] == 1 then
				setElementData(loadedVehicle[id], "veh:AirRide", true)
			end
			
			if data["impound"] == 1 then
				setElementData(loadedVehicle[id], "veh:Impound", true)
			end
			
			if data["pj"] > 0 then
				setElementData(loadedVehicle[id], "veh:PaintJob", data["pj"])
			end
			
			setElementData(loadedVehicle[id], "veh:headlightOn", 0)
			setElementData(loadedVehicle[id], "veh:headlightColor", fromJSON(data["headlight"]))
			
			setVehicleFuelTankExplodable(loadedVehicle[id], false)
			
			setElementData(loadedVehicle[id], "veh:lockedTrunk", false)
			
			if data["health"] <= 400 then
				setElementData(loadedVehicle[id], "veh:EngineCrash", 1)
			else
				setElementData(loadedVehicle[id], "veh:EngineCrash", 0)
			end
			local handbrake = data["handbrake"]
			if handbrake == 1 then
				setElementFrozen(loadedVehicle[id], true)
			else
				setElementFrozen(loadedVehicle[id], false)
			end
			setElementData(loadedVehicle[id], "handbrake", handbrake)
			
			local thex = tonumber(data["x"]) or 0
			if thex < -4125 then
				setElementData(loadedVehicle[id], "parked", false)
			else
				setElementData(loadedVehicle[id], "parked", true)
			end
			
			setElementHealth(loadedVehicle[id], data["health"])
			setVehicleColor(loadedVehicle[id], data["r"], data["g"], data["b"], data["r1"], data["g1"], data["b1"])
			
			if not shop and data["owner"] > 0 and data["interior"] == 0 and data["dimension"] == 0 then
				setElementInterior(loadedVehicle[id], 255)
				setElementDimension(loadedVehicle[id], 65000)
			else
				setElementInterior(loadedVehicle[id], data["interior"])
				setElementDimension(loadedVehicle[id], data["dimension"])
			end
			
			setElementData(loadedVehicle[id], "veh:Int", data["interior"])
			setElementData(loadedVehicle[id], "veh:Dim", data["dimension"])
			setVehicleEngineState(loadedVehicle[id], false)
			if not shop then
				setElementData(loadedVehicle[id], "veh:Neon", data["neon"])
				if data["door"] == 1 then
					setElementData(loadedVehicle[id], "vDoorType", "scissor")
				end
			
				local carshop_id = tonumber(data["carshop_id"]) or 0
				local carshop_pos = tonumber(data["carshop_pos"]) or 0
				local carshop_price = tonumber(data["carshop_price"]) or 0
				setElementData(loadedVehicle[id], "veh:CarshopID", carshop_id)
				setElementData(loadedVehicle[id], "veh:CarshopPos", carshop_pos)
				setElementData(loadedVehicle[id], "veh:Price", carshop_price)
				if carshop_id > 0 then
					exports.enterprise:addVehicleToCarshop(loadedVehicle[id], carshop_id, carshop_pos)
				end
				
				local upgrades = fromJSON(data["upgrades"])
				for slot, upgrade in ipairs(upgrades) do
					if upgrade and tonumber(upgrade) > 0 then
						setElementData(loadedVehicle[id], "veh:Upgrade"..slot, upgrade)
					end
				end
				
				local chip = data["chip"]
				if chip == 1 then
					chip = true
					setElementData(loadedVehicle[id], "veh:Chip", true)
				else
					chip = false
				end
				
				local levels = fromJSON(data["levels"])
				setElementData(loadedVehicle[id], "veh:Level1", levels[1])
				setElementData(loadedVehicle[id], "veh:Level2", levels[2])
				setElementData(loadedVehicle[id], "veh:Level3", levels[3])
				exports.handling:loadHandling(loadedVehicle[id], levels[1], levels[2], levels[3], chip, false, true)
			else
				exports.handling:loadHandling(loadedVehicle[id])
			end
			
			return loadedVehicle[id]
		end
	end
end
function onGuiHandbrakeStateChange(veh, state)
	setElementFrozen(veh, state)
end
addEvent("onGuiHandbrakeStateChange", true)
addEventHandler("onGuiHandbrakeStateChange", getRootElement(), onGuiHandbrakeStateChange)
addEvent("onServerVehicleEngineStateChange", true)
addEventHandler("onServerVehicleEngineStateChange", getRootElement(), function(v,s)
	setVehicleEngineState(v, s)
end)
addEvent("onServerVehicleLockStateChange", true)
addEventHandler("onServerVehicleLockStateChange", root, function(veh, state)
	setVehicleLocked(veh, state)
end)
function findVehicle(id)
	local id = tonumber(id)
	if loadedVehicle[id] then
		return loadedVehicle[id]
	else
		return false
	end
end
local tempVehs = {}
function createTempVehicle(element, model)
	if element and model then
		local thisID = -(#tempVehs+1)
		local x,y,z = getElementPosition(element)
		local rx,ry,rz = getElementRotation(element)
		x = x + ( ( math.cos ( math.rad ( rz ) ) ) * 5 )
		y = y + ( ( math.sin ( math.rad ( rz ) ) ) * 5 )
		local vehicle = createVehicle(model, x,y,z,rx,ry,rz)
		local dim, int = getElementDimension(element), getElementInterior(element)
		if vehicle then
			tempVehs[vehicle] = thisID
			setElementHealth(vehicle, 1000)
			setVehicleColor ( vehicle, 255, 255, 255, 255, 255, 255)
			setVehicleHeadLightColor ( vehicle, 255, 255, 255 )
	
			setElementData(vehicle, "veh:EngineCrash", 0)		
			setElementData(vehicle, "dbid", thisID)
			setElementData(vehicle, "veh:Owner", -1)
			setElementData(vehicle, "veh:FuelData", 100)
			setElementData(vehicle, "veh:Engine", 0)
			setElementData(vehicle, "veh:Lights", 0)
			setElementData(vehicle, "veh:Faction", 0)
			setElementInterior(vehicle, int)
			setElementDimension(vehicle, dim)
			
			setElementInterior(vehicle, int)
			setElementData(vehicle, "veh:Int", int)	
			setElementDimension(vehicle, dim)
			setElementData(vehicle, "veh:Dim", dim)
			
			setVehicleEngineState(vehicle, false)
			exports.handling:loadHandling(vehicle)
			setVehiclePlateText(vehicle, "")
			setVehicleRespawnPosition(vehicle, x,y,z,rx,ry,rz)
		end
	end
end
function vehicleExploded()
	if tempVehs[source] then
		destroyElement(source)
		return
	end
	setTimer(respawnVehicle, 5000, 1, source)
	setVehicleDamageProof(source, false)
end
addEventHandler("onVehicleExplode", getRootElement(), vehicleExploded)
function vehicleExit(thePlayer, seat)
	if tempVehs[source] and seat == 0 then
		destroyElement(source)
	end
end
addEventHandler("onVehicleExit", getRootElement(), vehicleExit)
function createShopVehicle(targetPlayer, model, x, y, z, rx, ry, rz, int, dim, r, g, b, r1, g1, b1, var1, var2)
	local owner = tonumber(getElementData(targetPlayer, "dbid")) or 0
	if owner > 0 then
		dbExec(newsql, "INSERT INTO cars SET interior = ?, dimension = ?, model = ?, x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, r = ?, g = ?, b = ?, r1 = ?, g1 = ?, b1 = ?, owner = ?, health = ?, var1 = ?, var2 = ?", int, dim, model, -4125.1044921875, -1482.158203125, 6.2468748092651, rx, ry, rz, r, g, b, r1, g1, b1, owner, 1000, var1, var2)
		dbQuery(function(qh, targetPlayer, x, y, z)
			local res, rows, err = dbPoll(qh, 0)
			if rows > 0 then
				local data = res[1]
				local veh = loadOneVehicle(data, true)
				setElementPosition(veh, x, y, z)
				exports.inventory:giveItem(targetPlayer, 29, data["id"])
				exports.streamer:addVehicleToPlayer(getElementData(targetPlayer, "dbid"), veh)
				warpPedIntoVehicle(targetPlayer, veh)
				setElementFrozen(veh, false)
			end
		end, {targetPlayer, x, y, z}, newsql, "SELECT * FROM cars WHERE id = LAST_INSERT_ID()")
	end
end 
addEvent("createShopVehicle", true)
addEventHandler("createShopVehicle", getRootElement(), createShopVehicle)
function getCarOwner(player, cmd)
	if(not exports.core:isSuperAdmin(player))then
		return
	end
	local veh = getPedOccupiedVehicle(player)
	if(not veh)then
		outputChatBox("", player, 255, 30, 30, true)
		return
	end
	local id = tonumber(getElementData(veh, "veh:Owner") or -1)
	if(id>0)then
		dbQuery(function(qh)
			local res, rows, errorMsg = dbPoll(qh, 0)
			if rows > 0 then
				for k,v in pairs(res) do
					outputChatBox(""..v["charactername"]:gsub("_", " "), player, 30, 100, 250, true)
				end
			end
		end, newsql, "SELECT * FROM players WHERE id = ? LIMIT 1",id)
	else
		outputChatBox("", player, 255, 30, 30, true)
	end
end
addCommandHandler("getcarowner", getCarOwner)
addCommandHandler("getvehowner", getCarOwner)
addEvent("startStopVehicle", true)
addEventHandler("startStopVehicle", root, function(veh, state)
	triggerClientEvent(root, "startStopVehicle", root, veh, state)
end)