local M = {}
M.type = "auxilliary"
M.relevantDevice = nil
--M.throttle 
local device = nil
local batteryApplied = false
local storage = nil
--set efficiency coef for energy production. 1kwh/m² at ideal sunlight. Roof has 1.7m² area
local efficiencyCoef = 1
local roofArea = 1.7
local energyGain = 1
local energyProduced = 0
local sin = math.sin
local solarPanelDamage = nil
local solarPanelDeformGroup = nil
local solarPanelState = "intact"

local function lerp(a,b,t) 
    return a * (1-t) + b * t 
end

local function checkIfBatteryApplied(storage)
  device = powertrain.getDevice("mainEngine")
  if device then
	  for _, s in pairs(device.registeredEnergyStorages) do
		storage = energyStorage.getStorage(s)
	  end
  end
  if storage then
	  if storage.energyType ~= "electricEnergy" then
		batteryApplied = false
	    print("The car has no Battery applied, which could be charged by the Solar Panel Roof, disabling functionality")
		return
	  end
	batteryApplied = true
  end
end

local function updateGFX(dt) 
	--Check if panel is broken
    solarPanelDamage = beamstate.deformGroupDamage[solarPanelDeformGroup] and beamstate.deformGroupDamage[solarPanelDeformGroup].damage or 0
	if solarPanelDamage >= 0.0001 and solarPanelState == "intact" then
		gui.message({txt = "Solar Panel damaged", context = {}}, 10, "vehicle.damage.mildOverrev")
		solarPanelState = "broken"
	end

	--Check if battery is applied, then add energy to battery depending on day time
	--Sun goes up at 6:00 (0.75), goes down at 18:00 (0.25) | *3600000 kwh to J
	if batteryApplied == true and solarPanelState ~= "broken" then
	--set device and storage (again)
		device = powertrain.getDevice("mainEngine")
		for _, s in pairs(device.registeredEnergyStorages) do
			storage = energyStorage.getStorage(s)
		end
	  local hasEnergy = false
	  
	  obj:queueGameEngineLua('be:getPlayerVehicle(0):queueLuaCommand("ingameTime =" .. serialize(core_environment.getTimeOfDay().time))')
	  obj:queueGameEngineLua('be:getPlayerVehicle(0):queueLuaCommand("cloudiness =" .. serialize(core_environment.getCloudCover()))')

		if ingameTime then
			if ingameTime <= 0.25 then
				efficiencyCoef = clamp(sin(-ingameTime * 6.2 + 1.55), 0, 1)
			elseif ingameTime >= 0.75 then
				efficiencyCoef = clamp(-sin(math.pow(ingameTime, 1.4)*4.7), 0, 1)
			else
				efficiencyCoef = 0
			end
			--print("Efficiency: " .. efficiencyCoef .. " Time: " .. ingameTime)
		elseif not ingameTime and efficiencyCoef ~= 1 then
			efficiencyCoef = 1
		end
		
		if not cloudiness then
			cloudiness = 1
		end

		if storage then
		  energyProduced = ((dt / 1) * energyGain)/1000	--calculating how many watt hours were created in the time of dt, converting to kWh

		  storage.storedEnergy = clamp(storage.storedEnergy + ((roofArea * energyProduced * efficiencyCoef * lerp(1, 0.5, cloudiness/5)) * 3600000), 0, storage.energyCapacity)	--adding energy to battery

		  hasEnergy = hasEnergy or storage.storedEnergy > 0
		end
	--print(storage.storedEnergy .. " and " .. dt)
	end
end

local function init(jbeamData) 
	roofArea = jbeamData.solarRoofArea or 1.7
	energyGain = jbeamData.solarRoofEnergyGain or 1
	obj:queueGameEngineLua('be:getPlayerVehicle(0):queueLuaCommand("ingameTime =" .. serialize(core_environment.getTimeOfDay().time))')
	obj:queueGameEngineLua('be:getPlayerVehicle(0):queueLuaCommand("cloudiness =" .. serialize(core_environment.getCloudCover()))')
	checkIfBatteryApplied()
	--Get deformGroup name for panel damage
	solarPanelDeformGroup = jbeamData.solarPanelDeformGroup or "solarPanel"
	solarPanelState = "intact"
end

local function reset() 
	obj:queueGameEngineLua('be:getPlayerVehicle(0):queueLuaCommand("ingameTime =" .. serialize(core_environment.getTimeOfDay().time))')
	obj:queueGameEngineLua('be:getPlayerVehicle(0):queueLuaCommand("cloudiness =" .. serialize(core_environment.getCloudCover()))')
	checkIfBatteryApplied()
	solarPanelState = "intact"
end

M.init = init
M.reset = reset
M.updateGFX = updateGFX

return M