-- This Source Code Form is subject to the terms of the bCDDL, v. 1.1.
-- If a copy of the bCDDL was not distributed with this
-- file, You can obtain one at http://beamng.com/bCDDL-1.1.txt

local M = {}

local function onReset()
  electrics.values['openFR'] = 0
  electrics.values['openFR_input'] = 0
  electrics.values['openFL'] = 0
  electrics.values['openFL_input'] = 0
  electrics.values['openRR'] = 0
  electrics.values['openRR_input'] = 0
  electrics.values['boot'] = 0
  electrics.values['boot_input'] = 0

  
  electrics.values['tailgate_lower_input'] = 0
  electrics.values['tailgate_lower'] = 0
  electrics.values['tailgate_lower_t1'] = 0
  electrics.values['Sunroof_Shade_input'] = 0
  electrics.values['Sunroof_Shade'] = 0
  electrics.values['Sunroof_Shade_t1'] = 0
  electrics.values['tailgate_input'] = 0
  electrics.values['tailgate'] = 0
  electrics.values['tailgate_t1'] = 0
  
  electrics.values['camera_to_vehicle_distance'] = {0, 0, 0, 0, 0, 0}
  
  electrics.values['doorFLCoupler_notAttached'] = 0
  electrics.values['doorFRCoupler_notAttached'] = 0
  electrics.values['doorRLCoupler_notAttached'] = 0
  electrics.values['doorRRCoupler_notAttached'] = 0
  electrics.values['FL_Filter'] = 1
  electrics.values['FR_Filter'] = 1
  electrics.values['RL_Filter'] = 1
  electrics.values['RR_Filter'] = 1
  
  electrics.values['vehicleIsReloaded'] = 1
  electrics.values['FilterNeedsToChange'] = 0
end

local sfx_tailgateButton

function updateGlass(input, currentValue, dt)
  return clamp((currentValue + input * dt), -1, 0)
end
function timeToRadians(currentTime, mod, dt)
  return (currentTime + dt*math.pi*2) % (math.pi*mod)
end
function cosFunc(currentTime)
  return -(-math.cos(currentTime)*0.5+0.5)
end

function updateGeneral(input, currentTime, currentValue, dt)
  local t2 = timeToRadians(currentTime, 2, dt)
  if (currentTime < math.pi and t2 > math.pi) or (currentTime < math.pi*2 and t2 < currentTime) then
    input = 0
  else
    currentValue = cosFunc(currentTime)
  end
  currentTime = t2
  return input, currentTime, currentValue
end

function sfx_play(condition, varName, volumeLevel, varName2, varName_up, varName2_up)
  if condition == 0 then
    obj:cutSFX(varName)
    obj:cutSFX(varName_up)
    obj:stopSFX(varName)
    obj:stopSFX(varName_up)
    if varName2 then
      obj:cutSFX(varName2)
      obj:cutSFX(varName2_up)
      obj:stopSFX(varName2)
      obj:stopSFX(varName2_up)
    end
  else
    obj:cutSFX(varName2)
    obj:stopSFX(varName2)
    obj:setVolume(varName, volumeLevel)
    obj:playSFX(varName)
  end
end

function doorFilter(couplerState, windowState, filterState, doorBroken_u, doorBroken_l, windowBroken, quarterWindowBroken, quarterWindowState)
  if windowState < 0 or couplerState == 1 or quarterWindowState < 0 or doorBroken_u or doorBroken_l or windowBroken or quarterWindowBroken then
    if filterState == 1 then
      filterState = 0
      electrics.values.FilterNeedsToChange = 1
    end
  elseif filterState == 0 then
    filterState = 1
    electrics.values.FilterNeedsToChange = 1
  end
  return filterState
end

function changeCabinFilter()
  if electrics.values.FilterNeedsToChange == 1 and initialFilter ~= nil then
    electrics.values.FilterNeedsToChange = 0
    if electrics.values.FL_Filter == 1 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 1 and electrics.values.RR_Filter == 1 then
      obj:queueGameEngineLua("core_sounds.cabinFilterStrength = " .. (initialFilter*1)) 
    end
    if (electrics.values.FL_Filter == 0 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 1 and electrics.values.RR_Filter == 1) or (electrics.values.FL_Filter == 1 and electrics.values.FR_Filter == 0 and electrics.values.RL_Filter == 0 and electrics.values.RR_Filter == 1) or (electrics.values.FL_Filter == 1 and electrics.values.FR_Filter == 0 and electrics.values.RL_Filter == 1 and electrics.values.RR_Filter == 0) then 
      obj:queueGameEngineLua("core_sounds.cabinFilterStrength = " .. (initialFilter*0.4)) 
    end
    if (electrics.values.FL_Filter == 1 and electrics.values.FR_Filter == 0 and electrics.values.RL_Filter == 1 and electrics.values.RR_Filter == 1) or (electrics.values.FL_Filter == 1 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 0 and electrics.values.RR_Filter == 1) or (electrics.values.FL_Filter == 1 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 1 and electrics.values.RR_Filter == 0) or (electrics.values.FL_Filter == 1 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 0 and electrics.values.RR_Filter == 0) then 
      obj:queueGameEngineLua("core_sounds.cabinFilterStrength = " .. (initialFilter*0.6)) 
    end
    if (electrics.values.FL_Filter == 0 and electrics.values.FR_Filter == 0 and electrics.values.RL_Filter == 1 and electrics.values.RR_Filter == 1) or (electrics.values.FL_Filter == 0 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 0 and electrics.values.RR_Filter == 1) or (electrics.values.FL_Filter == 0 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 1 and electrics.values.RR_Filter == 0) or (electrics.values.FL_Filter == 1 and electrics.values.FR_Filter == 0 and electrics.values.RL_Filter == 0 and electrics.values.RR_Filter == 0) then 
      obj:queueGameEngineLua("core_sounds.cabinFilterStrength = " .. (initialFilter*0.3)) 
    end
    if (electrics.values.FL_Filter == 0 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 0 and electrics.values.RR_Filter == 0) or (electrics.values.FL_Filter == 0 and electrics.values.FR_Filter == 1 and electrics.values.RL_Filter == 1 and electrics.values.RR_Filter == 0) or (electrics.values.FL_Filter == 0 and electrics.values.FR_Filter == 0 and electrics.values.RL_Filter == 0 and electrics.values.RR_Filter == 1) or (electrics.values.FL_Filter == 0 and electrics.values.FR_Filter == 0 and electrics.values.RL_Filter == 0 and electrics.values.RR_Filter == 0) then 
      obj:queueGameEngineLua("core_sounds.cabinFilterStrength = " .. (initialFilter*0.2)) 
    end
  end
end

function checkIfTheVehicleIsReloaded()
  if electrics.values.vehicleIsReloaded == 1 then
    if initialFilter == nil then
      obj:queueGameEngineLua("initialFilter = core_sounds.cabinFilterStrength be:getPlayerVehicle(0):queueLuaCommand('initialFilter = '..initialFilter)")
      return
    end
    obj:queueGameEngineLua("core_sounds.cabinFilterStrength = " .. (initialFilter or 1))
    electrics.values.vehicleIsReloaded = 0
  end
end

function updateCameraDistance()
  obj:queueGameEngineLua("cameraPosition_xyz = {core_camera.getPosition().x, core_camera.getPosition().y, core_camera.getPosition().z} be:getPlayerVehicle(0):queueLuaCommand('electrics.values.camera_to_vehicle_distance[4] = ' ..cameraPosition_xyz[1].. ' electrics.values.camera_to_vehicle_distance[5] = ' ..cameraPosition_xyz[2].. ' electrics.values.camera_to_vehicle_distance[6] = ' ..cameraPosition_xyz[3].. ' electrics.values.camera_to_vehicle_distance[1] = obj:getPosition().x electrics.values.camera_to_vehicle_distance[2] = obj:getPosition().y electrics.values.camera_to_vehicle_distance[3] = obj:getPosition().z')")
end

function checkIfBacklightIsBroken()
  if electrics.values.backlight_Filter == 1 then
    if #backlight == 0 then
      for _, b in pairs(v.data.beams) do 
        if b.deformGroup == "backlight_break" then 
          table.insert(backlight, b.cid)
        end 
      end
    end
    local conditionIsMet = false
    for i=1, #backlight do
      if math.abs(1 - obj:getBeamDebugDeformation(backlight[i])) > 0.05 then
        conditionIsMet = true
        break
      end
    end
    return conditionIsMet
  else
    return true
  end
end

local function updateGFX(dt)
  
  checkIfTheVehicleIsReloaded()
  
  if electrics.values.openFR_input ~= 0 then electrics.values.openFR = updateGlass(electrics.values.openFR_input, electrics.values.openFR, 0.4*dt) end
  if electrics.values.openRR_input ~= 0 then electrics.values.openRR = updateGlass(electrics.values.openRR_input, electrics.values.openRR, 0.4*dt) end
  if electrics.values.openFL_input ~= 0 then electrics.values.openFL = updateGlass(electrics.values.openFL_input, electrics.values.openFL, 0.4*dt) end
  if electrics.values.boot_input ~= 0 then electrics.values.boot = updateGlass(electrics.values.boot_input, electrics.values.boot, 0.4*dt) end
  
  if electrics.values.tailgate_lower_input == 1 then 
    electrics.values.tailgate_lower_input, electrics.values.tailgate_lower_t1, electrics.values.tailgate_lower = updateGeneral(electrics.values.tailgate_lower_input, electrics.values.tailgate_lower_t1, electrics.values.tailgate_lower, 1*dt)
  end
  if electrics.values.Sunroof_Shade_input == 1 then 
    electrics.values.Sunroof_Shade_input, electrics.values.Sunroof_Shade_t1, electrics.values.Sunroof_Shade = updateGeneral(electrics.values.Sunroof_Shade_input, electrics.values.Sunroof_Shade_t1, electrics.values.Sunroof_Shade, 1*dt)
  end
  if electrics.values.tailgate_input == 1 then 
    electrics.values.tailgate_input, electrics.values.tailgate_t1, electrics.values.tailgate = updateGeneral(electrics.values.tailgate_input, electrics.values.tailgate_t1, electrics.values.tailgate, 0.1*dt)
  end
  
  electrics.values.FL_Filter = doorFilter(electrics.values.doorFLCoupler_notAttached, electrics.values.openFL, electrics.values.FL_Filter, obj:beamIsBroken(2474), obj:beamIsBroken(2483), obj:beamIsBroken(2541), obj:beamIsBroken(2520), 0)
  electrics.values.FR_Filter = doorFilter(electrics.values.doorFRCoupler_notAttached, electrics.values.openFR, electrics.values.FR_Filter, obj:beamIsBroken(2633), obj:beamIsBroken(2642), obj:beamIsBroken(2700), obj:beamIsBroken(2679), 0)
  electrics.values.RL_Filter = doorFilter(electrics.values.doorRLCoupler_notAttached, electrics.values.boot, electrics.values.RL_Filter, obj:beamIsBroken(2806), obj:beamIsBroken(2813), obj:beamIsBroken(2847), false, 0)
  electrics.values.RR_Filter = doorFilter(electrics.values.doorRRCoupler_notAttached, electrics.values.openRR, electrics.values.RR_Filter, obj:beamIsBroken(2927), obj:beamIsBroken(2934), obj:beamIsBroken(2968), false, 0)
  
  changeCabinFilter()
end

local function open_glass_FR(value) electrics.values.openFR_input = -value end
local function close_glass_FR(value) electrics.values.openFR_input = value end
local function open_glass_FL(value) electrics.values.openFL_input = -value end
local function close_glass_FL(value) electrics.values.openFL_input = value end
local function open_glass_RR(value) electrics.values.openRR_input = -value end
local function close_glass_RR(value) electrics.values.openRR_input = value end
local function open_glass_RL(value) electrics.values.boot_input = -value end
local function close_glass_RL(value) electrics.values.boot_input = value end

local function tailgate_lower(value) electrics.values.tailgate_lower_input = 1 end
local function Sunroof_Shade(value) electrics.values.Sunroof_Shade_input = 1 end

local function tailgate(value) 
  if electrics.values.tailgate_t1 < math.pi then guihooks.message("Lowering telescopic tailgate") end
  if electrics.values.tailgate_t1 >= math.pi then guihooks.message("Raising telescopic tailgate") end
  electrics.values.tailgate_input = 1 
  sfx_tailgateButton  = sounds.createSoundscapeSound("tailgateButton")
  sfx_play(1, sfx_tailgateButton, 0.6, sfx_tailgateButton)
end

local function RR_door(value)
  if electrics.values.doorFRCoupler_notAttached == 1 then 
    controller.getControllerSafe('doorRRCoupler').toggleGroup() return
  else 
    guihooks.message("Open the front door first")
  end
end
local function RL_door(value)
  if electrics.values.doorFLCoupler_notAttached == 1 then 
    controller.getControllerSafe('doorRLCoupler').toggleGroup() return
  else 
    guihooks.message("Open the front door first")
  end
end

-- public interface
M.onInit    = onReset
M.onReset   = onReset
M.updateGFX = updateGFX

M.open_glass_FR = open_glass_FR
M.close_glass_FR = close_glass_FR
M.open_glass_RR = open_glass_RR
M.close_glass_RR = close_glass_RR
M.open_glass_FL = open_glass_FL
M.close_glass_FL = close_glass_FL
M.open_glass_RL = open_glass_RL
M.close_glass_RL = close_glass_RL

M.RR_door = RR_door
M.RL_door = RL_door

M.tailgate = tailgate

M.tailgate_lower = tailgate_lower
M.Sunroof_Shade = Sunroof_Shade

--local cid for _, b in pairs (v.data.beams) do if b.tag == "myTag" then cid = b.cid end end print(cid)
--copy this function to the vlua terminal to get a beam cid (a beam has to have a tag defined in a jbeam file), 
--for example: ["d7l", "b9ll", {"tag": "myTag"}],

return M