-- 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 frontGearHydro = nil
local leftGearHydro = nil
local rightGearHydro = nil

local mainClosedThreshold = 0.62
local frontClosedThreshold = 0.795

local mainSmoother = newTemporalSmoothingNonLinear(1, 1, 1)
local frontSmoother = newTemporalSmoothingNonLinear(1, 1, 1)
local frontClosingSmoother = newTemporalSmoothingNonLinear(1, 1, 0)
local mainClosingSmoother = newTemporalSmoothingNonLinear(1, 1, 0)

local function init()
  --nil beams just in case
  --UPDATE : in case of what??? (mar 2018) 
  frontGearHydro = nil
  leftGearHydro  = nil
  rightGearHydro = nil
  
  --init electrics
  electrics.values["geardoor_F"] = 0
  electrics.values["geardoor_M"] = 0
  electrics.values["geardoor_F_closing"] = 0
  electrics.values["geardoor_M_closing"] = 0
  electrics.values["gear_L_extent"] = 0
  electrics.values["gear_R_extent"] = 0
  
  --get beams
  for k,beam in pairs(v.data.beams) do
    if beam.name ~= nil then
      --assign things
      if beam.name == "frontgear" then frontGearHydro =   beam end
      if beam.name == "maingear_L" then leftGearHydro = beam end
      if beam.name == "maingear_R" then rightGearHydro = beam end
    end
  end
end

local function map(x, in_min, in_max, out_min, out_max)
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
end

local function updateDoors(dt)
  --get gear extents for gear door stuff
  if leftGearHydro ~= nil then
    local leftLength = obj:getBeamLengthRefRatio(leftGearHydro.cid)
    local leftFactor = math.max(map(leftLength, mainClosedThreshold, 1, 0, 1), 0)
    electrics.values["gear_L_extent"] = leftFactor
    electrics.values["gear_L_extentN"] = 1 - leftFactor
  end

  if rightGearHydro ~= nil then
    local rightLength = obj:getBeamLengthRefRatio(rightGearHydro.cid)
    local rightFactor = math.max(map(rightLength, mainClosedThreshold, 1, 0, 1), 0)
    electrics.values["gear_R_extent"] = rightFactor
    electrics.values["gear_R_extentN"] = 1 - rightFactor
  end
  
  --calculate the rest
  if leftGearHydro ~= nil or rightGearHydro ~= nil then
    local beam = leftGearHydro or rightGearHydro
    local mainLength = obj:getBeamLengthRefRatio(beam.cid)
    
    --set electrics
    if mainLength < mainClosedThreshold then
      electrics.values["geardoor_M"] = mainSmoother:get(0, dt)
    else
      electrics.values["geardoor_M"] = mainSmoother:get(1, dt)
    end
    
    if mainLength < 1 and mainLength > mainClosedThreshold then
      electrics.values["geardoor_M_closing"] = mainClosingSmoother:get(1, dt)
    else
      electrics.values["geardoor_M_closing"] = mainClosingSmoother:get(0, dt)
    end
  end
  
  if frontGearHydro ~= nil then
    local frontLength = obj:getBeamLengthRefRatio(frontGearHydro.cid)
    
    --set electrics
    if frontLength < frontClosedThreshold then
      electrics.values["geardoor_F"] = frontSmoother:get(0, dt)
    else
      electrics.values["geardoor_F"] = frontSmoother:get(1, dt)
    end
    
    if frontLength < 1 and frontLength > frontClosedThreshold then
      electrics.values["geardoor_F_closing"] = frontClosingSmoother:get(1, dt)
    else
      electrics.values["geardoor_F_closing"] = frontClosingSmoother:get(0, dt)
    end
  end
end

local gearLocked = true
local function updateSounds(dt)
  local gearSoundVal = 0
  
  --compute beam stuff
  if leftGearHydro ~= nil or rightGearHydro ~= nil then
    -- so we still get sound when one is broken
    local isBroken = true
    local beam = nil
    if leftGearHydro ~= nil then
      if not obj:beamIsBroken(leftGearHydro.cid) then
        isBroken = false 
        beam = leftGearHydro
      end
    end
    if rightGearHydro ~= nil then
      if not obj:beamIsBroken(rightGearHydro.cid) then
        isBroken = false 
        beam = rightGearHydro
      end
    end
    
    if isBroken then goto broken end 
    
    local mainLength = obj:getBeamLengthRefRatio(beam.cid)
    
    -- gear extend/retract sound
    if mainLength < 1 and mainLength > mainClosedThreshold then
      gearSoundVal = 1
    end
    
    -- gear lock sound
    if mainLength < 0.9 then gearLocked = false end
    if mainLength > 0.99 and not gearLocked then
      gearLocked = true
      sounds.playSoundOnceAtNode("A380-800_gearlock", beam.id1, 1.9)
    end
  end
  
  ::broken::
  electrics.values["gearsound"] = math.min(0.99, gearSoundVal)
end

local function updateGFX(dt)
  updateDoors(dt)
  updateSounds(dt)
end

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