--***********************************************************
--**                    THE INDIE STONE                    **
--***********************************************************

local VehicleCommands = {}
local Commands = {}

VehicleCommands.wantNoise = getDebug() or false

local noise = function(msg)
	if VehicleCommands.wantNoise then
		print('VehicleCommands: '..msg)
	end
end

function Commands.hotwireEngine(player, args)
	local electricSkill = args.electricSkill;
	player:getVehicle():tryHotwire(electricSkill);
end

function Commands.startEngine(player, args)
	local vehicle = player:getVehicle()
	local haveKey = args.haveKey;
	if vehicle then
		if vehicle:isDriver(player) then
			if true or vehicle:isEngineWorking() then
				vehicle:tryStartEngine(haveKey)
			else
				noise('engine not working')
			end
		else
			noise('player not driver')
		end
	else
		noise('player not in vehicle')
	end
end

function Commands.shutOff(player, args)
	local vehicle = player:getVehicle()
	if vehicle then
		if vehicle:isDriver(player) then
			vehicle:shutOff()
		else
			noise('player not driver')
		end
	else
		noise('player not in vehicle')
	end
end

function Commands.installPart(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		local keyvalues = part:getTable("install");
		local perks = keyvalues.skills;
		local success, failure = VehicleUtils.calculateInstallationSuccess(perks, player, args.perks);
		local item = InventoryItemFactory.CreateItem(args.item)
		if not item then
			noise('failed to create '..tostring(args.item))
			return
		end
		item:setID(args.itemID);
		if args.modData then
			for k,v in pairs(args.modData) do
				item:getModData()[k] = v
			end
		end
		if instanceof(item, "DrainableComboItem") then
			item:setUsedDelta(args.usedDelta)
		end
		item:setItemCapacity(args.contentAmount);
		item:setCondition(args.condition)
	
		if ZombRand(100) < success then
			part:setInventoryItem(item, args.mechanicSkill)
			local tbl = part:getTable("install")
			if tbl and tbl.complete then
				VehicleUtils.callLua(tbl.complete, vehicle, part)
			end
			vehicle:transmitPartItem(part)
			player:sendObjectChange('mechanicActionDone', { success = true, vehicleId = vehicle:getId(), partId = part:getId(), itemId = item:getID(), installing = true })
		elseif ZombRand(100) < failure then
			item:setCondition(item:getCondition() - ZombRand(5,10));
			player:sendObjectChange('addItem', { item = item })
			playServerSound("PZ_MetalSnap", player:getCurrentSquare());
			player:sendObjectChange('mechanicActionDone', { success = false, vehicleId = vehicle:getId(), partId = part:getId(), itemId = item:getID(), installing = true })
		else
			player:sendObjectChange('addItem', { item = item })
			player:sendObjectChange('mechanicActionDone', { success = false, vehicleId = vehicle:getId(), partId = part:getId(), itemId = item:getID(), installing = true })
		end
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.uninstallPart(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		local keyvalues = part:getTable("install");
		local perks = keyvalues.skills;
		local success, failure = VehicleUtils.calculateInstallationSuccess(perks, player, args.perks);
		if ZombRand(100) < success then
			local item = part:getInventoryItem()
			if item then
				VehicleUtils.lowerUninstalledItemCondition(part, item, args.mechanicSkill, player)
				part:setInventoryItem(nil)
				item:setItemCapacity(args.contentAmount);
				local tbl = part:getTable("uninstall")
				if tbl and tbl.complete then
					VehicleUtils.callLua(tbl.complete, vehicle, part, item)
				end
				vehicle:transmitPartItem(part)
				player:sendObjectChange('addItem', { item = item })
				player:sendObjectChange('mechanicActionDone', { success = true, vehicleId = vehicle:getId(), partId = part:getId(), itemId = nil, installing = false})
			else
				noise('part already uninstalled '..args.part)
			end
		elseif ZombRand(failure) < 100 then
			part:setCondition(part:getCondition() - ZombRand(5,10));
			vehicle:transmitPartCondition(part)
			playServerSound("PZ_MetalSnap", player:getCurrentSquare());
			player:sendObjectChange('mechanicActionDone', { success = false, vehicleId = vehicle:getId(), partId = part:getId(), itemId = nil, installing = false})
		end
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.fixPart(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		local item = part:getInventoryItem()
		if item then
			part:setCondition(args.condition)
			vehicle:transmitPartCondition(part)
			item:setCondition(args.condition)
			item:setHaveBeenRepaired(args.haveBeenRepaired)
			vehicle:transmitPartItem(part)
		else
			noise('part item is missing'..args.part)
		end
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.repairEngine(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById("Engine")
		if part then
			part:setCondition(args.condition)
			vehicle:transmitPartCondition(part)
		else
			noise('no such part Engine')
		end
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.takeEngineParts(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById("Engine")
		if part then
			part:setCondition(0)
			vehicle:transmitPartCondition(part)
		else
			noise('no such part Engine')
		end
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.setContainerContentAmount(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		part:setContainerContentAmount(args.amount)
		vehicle:transmitPartModData(part)
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.toggleHeater(player, args)
	local vehicle = player:getVehicle();
	if vehicle then
		local part = vehicle:getPartById("Heater");
		if part then
			part:getModData().active = args.on;
			part:getModData().temperature = args.temp;
			vehicle:transmitPartModData(part);
		end
	else
		noise('player not in vehicle');
	end
end

function Commands.setHeadlightsOn(player, args)
	local vehicle = player:getVehicle()
	if vehicle then
		vehicle:setHeadlightsOn(args.on)
	else
		noise('player not in vehicle')
	end
end

function Commands.setTrunkLocked(player, args)
	local vehicle = player:getVehicle()
	if vehicle then
		vehicle:setTrunkLocked(args.locked)
	else
		noise('player not in vehicle')
	end
end

function Commands.setStoplightsOn(player, args)
	local vehicle = player:getVehicle()
	if vehicle then
		vehicle:setStoplightsOn(args.on)
	else
		noise('player not in vehicle')
	end
end

function Commands.setTirePressure(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		part:setContainerContentAmount(args.psi, true, true)
		local wheelIndex = part:getWheelIndex()
		-- TODO: sync inflation
		vehicle:setTireInflation(wheelIndex, part:getContainerContentAmount() / part:getContainerCapacity())
		vehicle:transmitPartModData(part)
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.setDoorLocked(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		if not part:getDoor() then
			noise('part ' .. args.part .. ' has no door')
			return
		end
		part:getDoor():setLocked(args.locked)
		--vehicle:toggleLockedDoor(part, player, args.locked)
		vehicle:transmitPartDoor(part)
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.setDoorOpen(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		if not part:getDoor() then
			noise('part ' .. args.part .. ' has no door')
			return
		end
		part:getDoor():setOpen(args.open)
		vehicle:transmitPartDoor(part)
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.setWindowOpen(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		if not part:getWindow() then
			noise('part ' .. args.part .. ' has no window')
			return
		end
		part:getWindow():setOpen(args.open)
		vehicle:transmitPartWindow(part)
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.damageWindow(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		if not part:getWindow() then
			noise('part ' .. args.part .. ' has no window')
			return
		end
		part:getWindow():damage(tonumber(args.amount))
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.onHorn(player, args)
	local vehicle = player:getVehicle()
	local state = args.state;
	if vehicle then
		if state == "start" then
			vehicle:onHornStart();
		end
		if state == "stop" then
			vehicle:onHornStop();
		end
	else
		noise('player not in vehicle')
	end
end

function Commands.onBackSignal(player, args)
	local vehicle = player:getVehicle()
	local state = args.state;
	if vehicle then
		if state == "start" then
			vehicle:onBackMoveSignalStart();
		end
		if state == "stop" then
			vehicle:onBackMoveSignalStop();
		end
	else
		noise('player not in vehicle')
	end
end

function Commands.setLightbarLightsMode(player, args)
	local vehicle = player:getVehicle()
	local mode = tonumber(args.mode);
	if vehicle then
		vehicle:setLightbarLightsMode(mode)
	else
		noise('player not in vehicle')
	end
end

function Commands.setLightbarSirenMode(player, args)
	local vehicle = player:getVehicle()
	local mode = tonumber(args.mode);
	if vehicle then
		vehicle:setLightbarSirenMode(mode)
		vehicle:setSirenStartTime(getGameTime():getWorldAgeHours())
	else
		noise('player not in vehicle')
	end
end

function Commands.putKeyInIgnition(player, args)
	local vehicle = player:getVehicle()
	if vehicle and vehicle:isDriver(player) then
		vehicle:putKeyInIgnition(args.key)
	else
		noise('player not driving vehicle')
	end
end

function Commands.removeKeyFromIgnition(player, args)
	local vehicle = player:getVehicle()
	if vehicle and vehicle:isDriver(player) then
		vehicle:removeKeyFromIgnition()
	else
		noise('player not driving vehicle')
	end
end

function Commands.putKeyOnDoor(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		vehicle:putKeyOnDoor(args.key)
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.removeKeyFromDoor(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		vehicle:removeKeyFromDoor()
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.crash(player, args)
	local vehicle = getVehicleById(args.vehicle);
	if vehicle then
		vehicle:Damage(args.amount);
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.getKey(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local item = vehicle:createVehicleKey()
		if item then
			player:sendObjectChange("addItem", { item = item })
		end
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.repair(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		vehicle:repair()
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.repairPart(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		local part = vehicle:getPartById(args.part)
		if not part then
			noise('no such part '..tostring(args.part))
			return
		end
		part:repair()
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.remove(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		vehicle:permanentlyRemove()
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

function Commands.cheatHotwire(player, args)
	local vehicle = getVehicleById(args.vehicle)
	if vehicle then
		vehicle:cheatHotwire(args.hotwired, args.broken)
	else
		noise('no such vehicle id='..tostring(args.vehicle))
	end
end

VehicleCommands.OnClientCommand = function(module, command, player, args)
	if module == 'vehicle' and Commands[command] then
		local argStr = ''
		args = args or {}
		for k,v in pairs(args) do
			argStr = argStr..' '..k..'='..tostring(v)
		end
		noise('received '..module..' '..command..' '..tostring(player)..argStr)
		Commands[command](player, args)
	end
end

Events.OnClientCommand.Add(VehicleCommands.OnClientCommand)
