-- Module Functions --

local Chassis = {}

Chassis.driverSeat = root:WaitForChild("VehicleSeat")
print("ran chassis module")

function Chassis.InitializeSeats()
	driverSeat = root:WaitForChild("VehicleSeat")
	passengerSeats = {
		root:FindFirstChild("SeatFR"),
		root:FindFirstChild("SeatRL"),
		root:FindFirstChild("SeatRR")
	}
	local wheelRadius = root.SuspensionFL.WheelFrontLeft.Size.y/2
	driverSeat.MaxSpeed = maxSpeed * wheelRadius
end

function Chassis.InitializeDriving()
	print("initializing chassis driving")
	local constraints = root:WaitForChild("Constraints")
	local effects = root:WaitForChild("Effects")
	local scripts = root:WaitForChild("Scripts")
	
	-- Constraint tables always ordered FL, FR, RL, RR
	motors = {
		constraints:WaitForChild("MotorFL"),
		constraints:WaitForChild("MotorFR"),
		constraints:WaitForChild("MotorRL"),
		constraints:WaitForChild("MotorRR")
	}
	local strutSprings = {
		constraints:WaitForChild("StrutSpringFL"),
		constraints:WaitForChild("StrutSpringFR"),
		constraints:WaitForChild("StrutSpringRL"),
		constraints:WaitForChild("StrutSpringRR")
	}
	local torsionSprings = {
		constraints:WaitForChild("TorsionBarSpringFL"),
		constraints:WaitForChild("TorsionBarSpringFR"),
		constraints:WaitForChild("TorsionBarSpringRL"),
		constraints:WaitForChild("TorsionBarSpringRR")
	}
	
	redressMount = root:WaitForChild("RedressMount")
	
	steeringPrismatic = constraints:WaitForChild("SteeringPrismatic")
	steerMax = steeringPrismatic.UpperLimit
	
	setMotorTorque(100000)
	
	for _,s in pairs(strutSprings) do
		--s.Stiffness = springStiffness
	--	s.Damping = springDamping
	end
	for _,s in pairs(torsionSprings) do
		--adjustStrutSpring(s, gravityChange)
	end
	print("finished initializing chassis driving")
end

function Chassis.GetDriverSeat()
	if not driverSeat then warn("driverSeat uninitialized") end
	return driverSeat
end

function Chassis.GetPassengerSeats()
	if not passengerSeats then warn("passengerSeats uninitialized") end
	return passengerSeats
end

function Chassis.SetMotorVelocity(vel)
	for _,m in pairs(motors) do
		m.AngularVelocity = vel
	end
end

function Chassis.GetAverageVelocity()
	local t = 0
	for _,m in pairs(motors) do
		t = t + getMotorVelocity(m)
	end
	return t * (1/#motors)
end

function Chassis.EnableHandbrake()
	motors[3].AngularVelocity = 0
	motors[4].AngularVelocity = 0
	motors[3].MotorMaxTorque = breakingTorque
	motors[4].MotorMaxTorque = breakingTorque
end

function Chassis.UpdateSteering(steer, currentVel)
	local c = 0.2*(math.abs(currentVel)/maxSpeed)+1  --decrease steer value as speed increases to prevent tipping (handbrake cancels this)
	steer = steer/c
	print(steer)
	steeringPrismatic.TargetPosition = steer * steer * steer * steerMax
end

function Chassis.UpdateThrottle(currentVel, throttle)
	local targetVel = 0
	local motorTorque = 0
	if math.abs( throttle ) < 0.1 then
		-- Idling
		motorTorque = 100
		setMotorTorque( motorTorque )
	elseif math.abs(throttle * currentVel) > 0 then
		motorTorque = torque * throttle * throttle
		setMotorTorqueDamped( motorTorque )
		-- Arbitrary large number
		targetVel = math.sign( throttle ) * 10000
	else
		-- Breaking
		motorTorque = breakingTorque * throttle * throttle
		setMotorTorque( motorTorque )
	end
	Chassis.SetMotorVelocity( targetVel )
	end
	
local redressingState = false	
function Chassis.Redress()
	if redressingState then
		return
	end
	redressingState = true	
	local p = driverSeat.CFrame.Position + Vector3.new( 0,10,0 )
	local xc = driverSeat.CFrame.RightVector
	xc = Vector3.new(xc.x,0,xc.z)
	xc = xc.Unit
	local yc = Vector3.new(0,1,0)
	local zc = xc:Cross( yc )
	local cf = CFrame.new( p.x,p.y,p.z, xc.x,yc.x,zc.x, xc.y,yc.y,zc.y, xc.z,yc.z,zc.z ) 

	local targetAttachment = redressMount.RedressTarget
	
	targetAttachment.Parent = workspace.Terrain
	targetAttachment.Position = p
	targetAttachment.Axis = xc
	targetAttachment.SecondaryAxis = yc
	redressMount.RedressOrientation.Enabled = true
	redressMount.RedressPosition.Enabled = true
	wait(1.5)
	redressMount.RedressOrientation.Enabled = false
	redressMount.RedressPosition.Enabled = false
	targetAttachment.Parent = redressMount
	wait(2)
	redressingState = false
end

return Chassis
