-- 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 monitorBeams = {}
local callbackFuncs = {}

--CALLBACKS
local function breakTris(group)
  for _,tri in pairs(v.data.triangles) do
  print(tri.cid)
    --if tri.breakGroup == group then
      print(tri.breakGroup)
      if tri.cid ~= nil then
      obj:breakCollisionTriangle(tri.cid)
      end
    --end
  end
end

--CACHED NODES
local cachedNodes = {}

local function initCachedNodes()
  cachedNodes = {}
  for _, node in pairs(v.data.nodes) do
    local name = node.name
    if name == "wmlt" or name == "wmlr" or name == "wmlb" then
      cachedNodes[name] = node
    end
    if name == "wmrt" or name == "wmrr" or name == "wmrb" then
      cachedNodes[name] = node
    end
    if name == "wl1t" or name == "wl1b" or name == "wl1r" then
      cachedNodes[name] = node
    end
    if name == "wr1t" or name == "wr1b" or name == "wr1r" then
      cachedNodes[name] = node
    end
    if name == "fus10at" or name == "fus10bt" or name == "fus10ab" or name == "fus10bb"
    or name == "fus10alb" or name == "fus10arb" or name == "fus10alt" or name == "fus10art"
    or name == "fus10blb" or name == "fus10brb" or name == "fus10blt" or name == "fus10brt" then
      cachedNodes[name] = node
    end
    if name == "fus11t" or name == "fus11b" or name == "fus11lt" or name == "fus11rt"
    or name == "fus11rb" or name == "fus11lb" then
      cachedNodes[name] = node
    end
  end
end

--eventually
--obj:addParticleByNodesRelative(engine.smokeNodes[1].cid, engine.smokeNodes[2].cid, 5 + (15 * engine.warmup), 40, 0.2, 5 * engine.throttle)
local function frontSparks(group)
  if group ~= "fus_weld_A" then return end
  electrics.values.frontbroken = 1
  
  --whoops, front fell off ¯\_(ツ)_/¯
  controller.getController("an12_cuntroller").controlsEnabled = false
end

local function rearSparks(group)
  if group ~= "fus_weld_B" then return end
  electrics.values.rearbroken = 1
  --obj:addParticleByNodesRelative(cachedNodes["fus10alb"].cid, cachedNodes["fus11lb"].cid, 15, 13, 0.2, 25)
  --obj:addParticleByNodesRelative(cachedNodes["fus10arb"].cid, cachedNodes["fus11rb"].cid, 15, 13, 0.2, 25)
  --obj:addParticleByNodesRelative(cachedNodes["fus10alt"].cid, cachedNodes["fus11lt"].cid, 15, 13, 0.2, 25)
  --obj:addParticleByNodesRelative(cachedNodes["fus10art"].cid, cachedNodes["fus11rt"].cid, 15, 13, 0.2, 25)
end

--particles go like
--id1, id2, velocity, particleid, radius, density
local function wingSparks(group)
  if group ~= "wingL0" and group ~= "wingR0" then return end
  
  --add sperks
  if group == "wingL0" then
    obj:addParticleByNodesRelative(cachedNodes["wmlt"].cid, cachedNodes["wl1t"].cid, 5, 1, 0.2, 4)
    obj:addParticleByNodesRelative(cachedNodes["wmlr"].cid, cachedNodes["wl1r"].cid, 5, 1, 0.2, 4)
    obj:addParticleByNodesRelative(cachedNodes["wmlb"].cid, cachedNodes["wl1b"].cid, 5, 1, 0.2, 3)
  else
    obj:addParticleByNodesRelative(cachedNodes["wmrt"].cid, cachedNodes["wr1t"].cid, 5, 1, 0.2, 4)
    obj:addParticleByNodesRelative(cachedNodes["wmrr"].cid, cachedNodes["wr1r"].cid, 5, 1, 0.2, 4)
    obj:addParticleByNodesRelative(cachedNodes["wmrb"].cid, cachedNodes["wr1b"].cid, 5, 1, 0.2, 4)
  end
end

--BREAKGROUP_CALLBACKS
local function initBreakGroupMonitors()
  monitorBeams = {}
  local breakGroupsMonitored = {}
  local lastBreakGroup = nil
  for k,bm in pairs(v.data.beams) do
    if bm.breakGroup == "" or bm.breakGroup == nil then goto continue end
    
    --get name and type
    local bkgNames = bm.breakGroup
    local bkgType = bm.breakGroupType or 0
    if bkgType > 0 or bkgNames == nil then goto continue end
    
    --make a table if it's not one. this is my solution to multi breakgroups
    if type(bkgNames) ~= "table" then bkgNames = {bkgNames} end
    
    --check if we should monitor this
    for _, bkgName in pairs(bkgNames) do
      if bkgName ~= lastBreakGroup and breakGroupsMonitored[bkgName] == nil then
        breakGroupsMonitored[bkgName] = true
        lastBreakGroup = bkgName
        
        --print("breakgroup_callbacks , adding " .. bkgName)
        local cbBeamState = {}
        cbBeamState.beam = bm
        cbBeamState.state = "normal"
        cbBeamState.breakGroup = bkgName
        table.insert(monitorBeams, cbBeamState)
      end
    end
    ::continue::
  end
end

local function onInit()
  callbackFuncs = {}
  initBreakGroupMonitors()
  initCachedNodes()
  --usercode here
  --table.insert(callbackFuncs, breakTris)
  table.insert(callbackFuncs, frontSparks)
  table.insert(callbackFuncs, rearSparks)
  table.insert(callbackFuncs, wingSparks)
  --table.insert(callbackFuncs, function(name) print("callback" .. name) end) --test
end

local function onReset()
	onInit()
end

local function callCallbacks(bkg)
  for _,func in ipairs(callbackFuncs) do
    func(bkg)
  end
end

local function updateGFX(dt)
  --TEST
  --wingSparks("wingL0")
  
  for k,bm in pairs(monitorBeams) do
    local bork = obj:beamIsBroken(bm.beam.cid)
    if bork and bm.state ~= "broken" then
      callCallbacks(bm.breakGroup)
      bm.state = "broken"
    end
  end
end

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

return M