-- TERMS AND CONDITIONS OF USE:
--
--  These scripts are © Armstrong Powerhouse 2015.
--
--  Armstrong Powerhouse is not responsible for any damage caused from
--  the use of these files.
--
--  These scripts and any of the associated files may not used for any
--  purposes other than the original intended use.
--
--  These files must not be re-distributed in any form without prior permission.
--

C105_MSG_PROPAGATE_DEST =	105001
C105_MSG_PROPAGATE_ROUTE0 =	105002
C105_MSG_PROPAGATE_ROUTE1 =	105003


CAB_ENG_VOL_RISE_TIME = 0.5
CAB_ENG_VOL_FALL_TIME = 5

HERE = 'Assets/RSC/Class101RegionalRailways/RailVehicles/Diesel/Class101/AP/Scripts/'
MY_LUA = HERE .. 'my-lua/'

require(MY_LUA .. "util.lua")
require(MY_LUA .. "smooth.lua")
require(MY_LUA .. "curve.lua")

require(HERE .. "c101-traction.lua")
require(HERE .. "c105-destinations.lua")

local c101 = {
	debug = true,
	log_name = "c101",

	idle_transmission = {
		prev_throttle = 0,
		prev_gearlever = 0,
	},
	cab_eng_vol_smooth = smooth_new(1, 0),
	transmission_state_smooth = smooth_new(1, 0),
	cab_eng_idle_gear_vol_smooth = smooth_new((425 - 375) / 3, 0),
}

function OnControlValueChange(name, index, value)
	Call("SetControlValue", name, index, value)

	-- 105 specific stuff.
	if name == "DestinationsLight" then
		Call("ActivateNode", "dest_light", value > 0.5 and 1 or 0)
	end
	if name == "RouteNumberLight" then
		Call("ActivateNode", "route_light", value > 0.5 and 1 or 0)
	end

	if (name == "Destination" or name == "DestinationK" or name == "DestinationH") and c101.dests then
		c101.dests:on_cv_change(name, value)
	end
	
end

local function sync_control(name)
	OnControlValueChange(name, 0, Call("GetControlValue", name, 0))
end

function Initialise()
	c101.traction = C101_TRACTION.new()

	c101.has_rear_light = (Call("GetControlMinimum", "IsClass121", 0) ~= nil)
	c101.is_105 = (Call("GetControlMinimum", "IsClass105", 0) ~= nil)

	if c101.is_105 then
		c101.dests = C105_DESTINATIONS.new()
	end

	Call("BeginUpdate")
end

local vgear_to_gear = {
	{ x = 0, y = 0 },
	{ x = 1, y = 4 },
	{ x = 2, y = 3 },
	{ x = 3, y = 2 },
	{ x = 4, y = 1 },
}

local function handle_cab_eng_vol(smooth, dt)
	local throttle = math.floor(Call("GetControlValue", "VirtualThrottle", 0) * 4 + 0.5)
	local hi = 0.5
	local lo = 0

	if throttle >= 2 then
		hi = 1
		lo = 0.5
	end
	local target = hi

	if throttle == 0 then
		target = lo
	end

	if smooth.current_val < target then
		-- rising
		smooth:set_config(1 / CAB_ENG_VOL_RISE_TIME, 0)
	else
		-- falling
		smooth:set_config(1 / CAB_ENG_VOL_FALL_TIME, 0)
	end

	Call("SetControlValue", "CabEngVol", 0, smooth:val(dt, target))
end

local function handle_idle_transmission(ctx)
	local throttle = math.floor(Call("GetControlValue", "VirtualThrottle", 0) * 4 + 0.5)
	local gearlever = math.floor(Call("GetControlValue", "GearLever", 0) + 0.5)
	local idle_transmission = Call("GetControlValue", "IdleTransmission", 0)

	if idle_transmission == 0 and ctx.prev_throttle > 0 and throttle == 0 then
		Call("SetControlValue", "IdleTransmission", 0, 1)
	elseif idle_transmission == 1 and ctx.prev_gearlever ~= gearlever then
		Call("SetControlValue", "IdleTransmission", 0, 0)
	end
	ctx.prev_gearlever = gearlever
	ctx.prev_throttle = throttle
end

local function handle_transmission_state(smooth, dt)
	local gearlever = Call("GetControlValue", "GearLever", 0)
	local target = 0
	if gearlever > 0.5 then
		target = 1
	end

	local target_smoothed = smooth:val(dt, target)
	Call("SetControlValue", "TransmissionStateCab", 0, target_smoothed)
	Call("SetControlValue", "TransmissionState", 0, target == 0 and  target or target_smoothed)
end

local function handle_revdown()
	local revdown_flag = Call("GetControlValue", "RevDown1", 0) +
		Call("GetControlValue", "RevDown2", 0) +
		Call("GetControlValue", "RevDown3", 0) +
		Call("GetControlValue", "RevDown4", 0)
	local throttle = Call("GetControlValue", "VirtualThrottle", 0)
	local vrpm = Call("GetControlValue", "VirtualRPM", 0)

	if revdown_flag == 0 and throttle < 0.375 then
		if vrpm < 755 then
			Call("SetControlValue", "RevDown1", 0, 1)
		elseif vrpm < 1135 then
			Call("SetControlValue", "RevDown2", 0, 1)
		elseif vrpm < 1515 then
			Call("SetControlValue", "RevDown3", 0, 1)
		else
			Call("SetControlValue", "RevDown4", 0, 1)
		end
	end
	if revdown_flag == 1 and throttle > 0.375 then
		Call("SetControlValue", "RevDown1", 0, 0)
		Call("SetControlValue", "RevDown2", 0, 0)
		Call("SetControlValue", "RevDown3", 0, 0)
		Call("SetControlValue", "RevDown4", 0, 0)
	end
end

function handle_cab_eng_idle_gear_vol(smooth, dt)
	local vrpm = Call("GetControlValue", "TransmissionRPM", 0)
	local throttle = math.floor(Call("GetControlValue", "VirtualThrottle", 0) * 4 + 0.5)
	local val = 0

	if vrpm > 425 then
		vrpm = 425
	end
	if vrpm < 325 then
		vrpm = 325
	end
	if throttle == 1 and vrpm > 400 then
		vrpm = 400
	end
	if throttle == 0 then
		vrpm = 325
	end

	if smooth.current_val < vrpm then
		smooth.current_val = vrpm
		val = vrpm
	else
		val = smooth:val(dt, vrpm)
	end
	Call("SetControlValue", "CabEngIdleGearVol", 0, val)
end

function OnResume()
	c101.resumed = true
end

function Update(dt)

	if not c101.once then
		c101.once = true
		if c101.is_105 then
			sync_control("DestinationsLight")
			sync_control("RouteNumberLight")
			if not c101.resumed then
				c101.dests:resume(C105_DESTINATIONS.RESUME_FROM_RVNUM)
			else
				c101.dests:resume(C105_DESTINATIONS.RESUME_FROM_CONTROLS)
			end
			if Call("GetIsEngineWithKey") == 1 then
				c101.dests:propagate()
			end
		end
	end

	if Call("GetIsPlayer") == 1 and Call("GetIsEngineWithKey") == 1 then
		c101.traction:handle(dt)

		if Call("ControlExists", "CabLight", 0) == 1 then
			-- CabLight not available on Class 111 ...
			local lightval = math.floor(Call("GetControlValue", "CabLight", 0) + 0.5)
			Call("CabLight:Activate", lightval)
			if c101.has_rear_light then
				Call("CabLightRear:Activate", lightval)
			end
		end

		local vgear = math.floor(Call("GetControlValue", "VirtualGearLever", 0) + 0.5)
		Call("SetControlValue", "GearLever", 0, curve_yval(vgear_to_gear, vgear))

		handle_cab_eng_vol(c101.cab_eng_vol_smooth, dt)
		handle_idle_transmission(c101.idle_transmission)
		handle_transmission_state(c101.transmission_state_smooth, dt)
		handle_revdown()
		handle_cab_eng_idle_gear_vol(c101.cab_eng_idle_gear_vol_smooth, dt)

		Call("SetControlValue", "AudioWiperValue", 0, Call("GetWiperValue", 0, 0))
	else
		Call("CabLight:Activate", 0)
	end

	if Call("GetControlValue", "Active", 0) == 0 then
		c101.traction:ai_rpm(dt)
	end
end

function OnCameraEnter(cab, pass)
	log_debug(c101, "OnCameraEnter: cab " .. cab .. ", pass " .. pass)
	if pass > 0 then
		Call("SetControlValue", "InPass", 0, 1)
		Call("SetControlValue", "InCab", 0, 1)
	elseif cab > 0 then
		Call("SetControlValue", "InCab", 0, 1)
	end
end

function OnCameraLeave()
	Call("SetControlValue", "InCab", 0, 0)
	Call("SetControlValue", "InPass", 0, 0)
end

function OnConsistMessage(msg, param, direction)
	if c101.dests then
		c101.dests:on_consist_message(msg, param)
	end
	Call("SendConsistMessage", msg, param, direction)
end