-- 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 = {}
M.type = "auxiliary"
M.relevantDevice = "transfercase"

local rangeSelect = nil
local prevGearSelect = nil

local driveModesRange = nil
local driveModesTransfercase = nil
local driveModesDifferentials = nil

local shaft = nil
local rangeBox = nil

local hasBuiltPie = false

local function toggleRange()
	if rangeSelect == "low" then
	rangeSelect = "high"
	else
	rangeSelect = "low"
	end
end

local function setRangeMode(mode)
	rangeSelect = mode
end

local function serialize()
  return {
    mode4WD = shaft and shaft.mode or nil,
    modeSplit = splitBox and splitBox.mode or nil
  }
end

local function deserialize(data)
  if data then
    if shaft and data.mode4WD then
      set4WDMode(data.mode4WD)
    end
    if splitBox and data.modeRange then
      setRangeMode(data.modeRange)
    end
  end
end

local function updateGFX(dt)
	if (electrics.values.gear_M == 0 or prevGearSelect ~= electrics.values.gear_M) and (rangeBox.mode ~= rangeSelect) and splitBox then
		powertrain.setDeviceMode(rangeBox.name, rangeSelect)

		if (rangeBox.mode == "high" and highSplit == false) or (rangeBox.mode == "low" and lowSplit == false) then
			for _, c in ipairs(driveModesSplit) do
				c.setDriveMode(defaultSplitMode)
			end
		end
	end
	prevGearSelect = electrics.values.gear_M
end

local function init(jbeamData)
  shaft = powertrain.getDevice(jbeamData.shaftName)
  rangeBox = powertrain.getDevice(jbeamData.rangeBoxName)
  rangeSelect = jbeamData.defaultRange or "low"
  prevGearSelect = 0
  
  
  if shaft then
    electrics.values.mode4WD = shaft.mode == "connected" and 1 or 0
  end
  if rangeBox then
    electrics.values.modeRangeBox = rangeBox.mode == "low" and 1 or 0
  end
  
  
  if not hasBuiltPie then
    if shaft then
      core_quickAccess.addEntry(
        {
          level = "/powertrain/",
          generator = function(entries)
            local wdIcon
            if shaft.mode == "disconnected" then
              wdIcon = "radial_disconnected"
            else
              wdIcon = "radial_connected"
            end

            local wdEntry = {
              title = "ui.radialmenu2.powertrain.4WD_Mode",
              icon = wdIcon,
              onSelect = function()
                if shaft.mode == "disconnected" then
                  controller.getController(M.name).set4WDMode("connected")
                else
                  controller.getController(M.name).set4WDMode("disconnected")
                end
                return {"reload"}
              end
            }
            if shaft.mode == "connected" then
              wdEntry.color = "#ff6600"
            end
            table.insert(entries, wdEntry)
          end
        }
      )
    end
    if rangeBox then
      core_quickAccess.addEntry(
        {
          level = "/powertrain/",
          generator = function(entries)
            local rmIcon
            if rangeBox.mode == "low" then
              rmIcon = "radial_lowrangebox"
            else
              rmIcon = "radial_highrangebox"
            end

            local rmEntry = {
              title = "ui.radialmenu2.powertrain.rangebox_mode",
              icon = rmIcon,
              onSelect = function()
                if rangeBox.mode == "low" then
                  controller.getController(M.name).setRangeMode("high")
                else
                  controller.getController(M.name).setRangeMode("low")
                end
                return {"reload"}
              end
            }
            rmEntry.color = "#ff6600"
            table.insert(entries, rmEntry)
          end
        }
      )
    end
    hasBuiltPie = true
  end
end

local function initLastStage(jbeamData)
  local driveModesSplitNames = jbeamData.driveModesSplitNames or {}
  local driveModesRangeNames = jbeamData.driveModesRangeNames or {}
  local driveModesTransfercaseNames = jbeamData.driveModesTransfercaseNames or {}
  local driveModesDifferentialNames = jbeamData.driveModesDifferentialNames or {}

  driveModesDifferentials = nil
  for _, name in ipairs(driveModesDifferentialNames) do
    local c = controller.getController(name)
    if c then
      driveModesDifferentials = driveModesDifferentials or {}
      table.insert(driveModesDifferentials, c)
    end
  end

  driveModesTransfercase = nil
  for _, name in ipairs(driveModesTransfercaseNames) do
    local c = controller.getController(name)
    if c then
      driveModesTransfercase = driveModesTransfercase or {}
      table.insert(driveModesTransfercase, c)
    end
  end

  driveModesRange = nil
  for _, name in ipairs(driveModesRangeNames) do
    local c = controller.getController(name)
    if c then
      driveModesRange = driveModesRange or {}
      table.insert(driveModesRange, c)
    end
  end
end

M.init = init
M.initLastStage = initLastStage
M.updateGFX = updateGFX
M.toggleRange = toggleRange
M.setRangeMode = setRangeMode
M.serialize = serialize
M.deserialize = deserialize

return M
