local M = {}

local engtime = 0
local engtimer = 0
local particleAmount = 0
local ignkeySmoother = newExponentialSmoothing(6)
local fuelgaugeSmoother = newExponentialSmoothing(192)
local tempgaugeSmoother = newExponentialSmoothing(256)
local oilPressureSmoother = newExponentialSmoothing(24)
local engine = nil
local rpmToAV = 0.104719755
local originalIdlerpm = 500 * rpmToAV
local originalRoughness = 50
local min = math.min
local max = math.max
local htmlTexture = require("htmlTexture")
local OilGrade = 15000

local rfrsh = 0
local afrcalc = 0
local afrstring = ""
local afrmath = 0
local battvolt = 12

local function init()
   electrics.values.shiftlight = 0
   electrics.values.choke = 0
    electrics.values['clockh'] = 0
    electrics.values['clockmin'] = 0
	electrics.values['clocksec'] = 0
	electrics.values.afr = 15
    engine = powertrain.getDevice("mainEngine")
  originalIdlerpm = engine.idleAV * 0.5

    obj:queueGameEngineLua("extensions.loadModule('ui/uinavi')")
	htmlTexture.create("@sats_afr", "local://local/vehicles/satsuma_100/afr.html", 480, 280, 2, 'automatic')
    if electrics.values.turboBoost == nil
    then electrics.values.turboBoost = 0
end
rfrsh = 0
end

local function reset()
  originalRoughness = engine.idleAVReadErrorRange 
 
  electrics.values.fuelgauge = electrics.values.fuel
  electrics.values.tempgauge = electrics.values.watertemp
  electrics.values.AFRON = 1
  electrics.values.maxRPM = engine.maxPhysicalAV / rpmToAV
  electrics.values.limitRPM = engine.maxRPM
  electrics.values.rpmChrono = electrics.values.rpm
  --init()
end

function math.Clamp(val, lower, upper)
    return math.max(lower, math.min(upper, val))
end

local function updateGFX(dt)



   if electrics.values.rpm > 500 then electrics.values.battvolt = 14 else electrics.values.battvolt = 12 end 

   --fanbelts and cambelt etc etc

   if electrics.values.rpm > 100 then electrics.values.beltuberslow = 0.5 else electrics.values.beltuberslow = 0 end
   if electrics.values.rpm > 2300 then electrics.values.beltslow = 1 else electrics.values.beltslow = 0 end
   if electrics.values.rpm > 3000 then electrics.values.beltmid = 1 else electrics.values.beltmid = 0 end
   --timing chain
   if electrics.values.rpm > 100 then electrics.values.chainuberslow = 0.5 else electrics.values.chainuberslow = 0 end
   if electrics.values.rpm > 1300 then electrics.values.chainslow = 1 else electrics.values.chainslow = 0 end
   if electrics.values.rpm > 3000 then electrics.values.chainmid = 1 else electrics.values.chainmid = 0 end

   --ignition keyswitch logic

   electrics.values.ignkey = electrics.values.ignitionLevel

    electrics.values.ignkey = ignkeySmoother:get(electrics.values['ignkey'])

    if engine.starterEngagedCoef > 0 then

	electrics.values.fuelgauge = electrics.values.fuel * (electrics.values.rpmTacho / 700) * electrics.values.ignkey
	electrics.values.tempgauge = electrics.values.watertemp * (electrics.values.rpmTacho / 700)
	else
	electrics.values.fuelgauge = electrics.values.fuel * engine.ignitionCoef
	electrics.values.tempgauge = electrics.values.watertemp * engine.ignitionCoef end

	electrics.values.fuelgauge = fuelgaugeSmoother:get(electrics.values['fuelgauge'])
	electrics.values.tempgauge = max(tempgaugeSmoother:get(electrics.values['tempgauge']),  30)

   if electrics.values.rpmTacho < 700 and electrics.values.ignkey > 1 then
   electrics.values.chargewarn = 1 else electrics.values.chargewarn = 0  end


	--oil pressure "simulation"

     local oilMath1 = 200 - electrics.values.oiltemp
	 local oilMath2 = electrics.values.rpmTacho / OilGrade
	 local oilMath3 = oilMath1 * oilMath2
	 local oilMath4 = oilMath3 / 120
	 local oilMath5 = oilMath4 + 1.1
	 local oilMath6 =  math.min(engine.thermals.debugData.engineThermalData.oilMass / 0.87, 3)

     electrics.values.oilPressure = oilMath5 * oilMath6 * (math.Clamp(electrics.values.rpmTacho, 0, originalIdlerpm) / (originalIdlerpm))  / engine.wearFrictionCoef * engine.thermals.debugData.engineThermalData.oilLubricationCoef
	 electrics.values.oilPressure = oilPressureSmoother:get(electrics.values['oilPressure'])

	if electrics.values.oilPressure < 1.5 and engine.ignitionCoef > 0 then electrics.values.oilwarn = 1 else electrics.values.oilwarn = 0 end


 --Coolant pressure

 electrics.values.waterpress = electrics.values.watertemp / 5.5 - 6.2 + electrics.values.rpmTacho / 10000
 if electrics.values.waterpress < 0 then electrics.values.waterpress = 0.0001 else end

	--Clock
    local time = os.date("*t", os.time())
    local hour = time.hour % 12
    electrics.values['clockh'] = hour*30
    electrics.values['clockmin'] = time.min*6
	electrics.values['clocksec'] = time.min*1

    --autochoke
	local chokeCoef = math.Clamp(1 - math.Clamp(electrics.values.oiltemp, 0, 60) / 60, 0, 1)
	electrics.values.choke = chokeCoef
	engine.idleAV = math.Clamp(originalIdlerpm * 2  + (150 * chokeCoef), originalIdlerpm, 261.8)
	engine.idleAVReadErrorRange = originalRoughness  * (1 - chokeCoef)
	--print(engine.idleAV / rpmToAV) 


	--AFR crap
	if engine.ignitionCoef >  0.8
	then electrics.values.AFRON = 1
	else electrics.values.AFRON = 0
	end

	if electrics.values.rpm > 540 and electrics.values.ignkey > 0 then
	local afrrandom =  math.random()  * (1 - engine.instantEngineLoad)
	local afrBoostCoef = engine.intakeAirDensityCoef *  engine.forcedInductionCoef 
	afrcalc = (6 + afrrandom)  + (5 * (engine.thermals.debugData.engineThermalData.engineEfficiency / 0.47))  + (3  * afrBoostCoef) 
	
	else
	afrcalc = 20
	end

	if afrcalc > 18 then
	afrstring = "LEAN"
	end

	if afrcalc < 8 then
	afrstring = "RICH"
	end

 if engine.throttle > engine.maxIdleThrottle and chokeCoef > 0.1 and  math.random() * (1.0) < (0.033 * (engine.outputRPM / 8000)) then 
engine.ignitionCutTime = (engine.instantEngineLoad * 0.2) * chokeCoef
if engine.ignitionCutTime > 0.09 and playerInfo.anyPlayerSeated then 
guihooks.message("Engine cold! Use less throttle until warm.")
end
end

	if afrcalc > 8 and afrcalc < 18 then
	afrmath = math.floor(afrcalc * 10)/10

    if string.find(tostring(afrmath), "%.") then
    afrstring =  tostring(afrmath)
	else 
     afrstring =  tostring(afrmath).. ".0"
    end
	end

	rfrsh = rfrsh + 1
	
	if rfrsh > 12 then
	electrics.values.rpmChrono = electrics.values.rpm
	htmlTexture.call("@sats_afr", "updateAFR", afrstring)
	rfrsh = rfrsh * 0
	electrics.values.afr = afrcalc
	end
end



M.onInit = init
M.onReset = reset
M.updateGFX = updateGFX

return M