-- 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 = {}

--large scope
local dirCounter = 0.25

--HTML
local vehicleID = obj:getID()

--TYPES
local INCREMENT = 0
local CONTINUOUS = 1
local TOGGLE = 2

--serialize functions
local function boolOnOffSerialzer(setting)
  if setting.value then return "On" end
  return "Off"
end

local function defaultSettingSerializer(setting)
    local valueStr = tostring(setting.value)
    if setting.units ~= nil then
      valueStr = valueStr .. setting.units
    end
    return valueStr
end

--tweakable values
local fan1 = {
  name = "Fan #1",
  category = "Misc",
  electric = "fan1",
  value = false,
  serializer = boolOnOffSerialzer,
  type = TOGGLE
}

local fan2 = {
  name = "Fan #2",
  category = "Misc",
  electric = "fan2",
  value = false,
  serializer = boolOnOffSerialzer,
  type = TOGGLE
}

local fan3 = {
  name = "Fan #3",
  category = "Misc",
  electric = "fan3",
  value = false,
  serializer = boolOnOffSerialzer,
  type = TOGGLE
}

local decisionHeight = {
  name = "Decision Height",
  category = "Instruments",
  electric = "rv5m_target_input",
  max = 750,
  min = 0,
  increment = 10,
  value = 0,
  units = "m",
  type = INCREMENT
}

local targetSpeed = {
  name = "Target Speed",
  category = "Instruments",
  electric = "airspeed_target_kn",
  max = 320,
  min = 0,
  increment = 10,
  value = 0,
  units = "kn",
  type = INCREMENT
}

local altimeterAdjust = {
  name = "Altimeter Adjust",
  category = "Instruments",
  electric = "altimeterAdjust",
  max = 999999,
  min = -999999,
  increment = 10,
  value = 0,
  units = "ft",
  type = INCREMENT
}

--storage
local currentSelection = 1
local selections = {fan1, fan2, fan3, targetSpeed, decisionHeight, altimeterAdjust}
local currentDirection = 0
local lastScreenState = false
local screenTimeout = 0

--html
local function queueHtml(stuff)
  obj:queueGameEngineLua("be:getObjectByID("..vehicleID.."):queueJSUITexture('@an12_screen', '" .. stuff .. "')")
end

local function htmlScreenOn()
  screenTimeout = 5
  lastScreenState = true
  queueHtml("showSettings()")
end

local function htmlScreenOnLong()
  htmlScreenOn()
  screenTimeout = 60
end
  

local function htmlScreenOff()
  lastScreenState = false
  queueHtml("hideSettings()")
end

local function updateHtmlSetting(setting)
  local valueStr = setting.serializer(setting)
  queueHtml('updateSetting("' .. setting.id .. '", "' .. tostring(valueStr) .. '")')
end

local function addHtmlCategory(category)
  queueHtml('addCategory("' .. category .. '")')
end

local function updateHtmlSelection()
  local jsSelection = currentSelection - 1
  queueHtml("highlightSetting(" .. tostring(jsSelection) .. ")")
end

--api
local function selectNext()
  currentSelection = currentSelection + 1
  if currentSelection > #selections then currentSelection = 1 end
  updateHtmlSelection()
end

local function selectPrevious()
  currentSelection = currentSelection - 1
  if currentSelection == 0 then currentSelection = #selections end
  updateHtmlSelection()
end

local function selectFirst()
  currentSelection = 1
  updateHtmlSelection()
end

local function toggleCurrentValue()
local data = selections[currentSelection]
  data.value = not data.value
  
  if data.value then
    electrics.values[data.electric] = 1
  else
    electrics.values[data.electric] = 0 
  end
end

local function incrementCurrentValue()
   local data = selections[currentSelection]
   if data.type == TOGGLE then toggleCurrentValue() return end
   
   local newValue = math.min(data.value + (data.increment or 1), data.max)
   
   --set
   data.value = newValue
   electrics.values[data.electric] = newValue
end

local function decrementCurrentValue()
   local data = selections[currentSelection]
   if data.type == TOGGLE then toggleCurrentValue() return end
   
   local newValue = math.max(data.value - (data.increment or 1), data.min)
   
   --set
   data.value = newValue
   electrics.values[data.electric] = newValue
end

local function setDirection(dir)
  if dir > 0 then currentDirection = 1 end
  if dir < 0 then currentDirection = -1 end
  if dir == 0 then currentDirection = 0 end
  dirCounter = 0.25
end

--module
local htmlSetup = false
local function onInit()
  --init settings
  local id = 0
  for _, setting in pairs(selections) do
    electrics.values[setting.electric] = setting.value 
    setting.id = id
    setting.serializer = setting.serializer or defaultSettingSerializer
    id = id + 1
  end
  
  --setup html first time
  if not htmlSetup then
    obj:queueGameEngineLua('be:getObjectByID('..vehicleID..'):createUITexture("@an12_screen", "local://local/vehicles/an12/HTML/config.html", 512, 512, UI_TEXTURE_USAGE_AUTOMATIC, 30)')  
    htmlSetup = true
    
    --push all settings
    local currentCat = "Default"
    for _, setting in ipairs(selections) do
      local settingCat = setting.category or "Default"
      if settingCat ~= currentCat then
        queueHtml('addCategory("' .. settingCat .. '")')
        currentCat = settingCat
      end
      queueHtml('addSetting(' .. tostring(setting.id) .. ', "' .. setting.name .. '")')
    end
  end
  
  --screen off
  htmlScreenOff()
  
  --select first
  selectFirst()
end

local function onReset()
  onInit()
end


local function updateGFX(dt)
  --update screen display
  for _,setting in ipairs(selections) do
    updateHtmlSetting(setting)
  end
  
  --screen timeout
  if lastScreenState and screenTimeout > 0 then
    screenTimeout = screenTimeout - dt
    if screenTimeout <= 0 then
      htmlScreenOff()
    end
  end
  
  --dir counter
  dirCounter = dirCounter - dt
  if dirCounter < 0 then
    dirCounter = 0.25
    if currentDirection > 0 then
      incrementCurrentValue()
    elseif currentDirection < 0 then
      decrementCurrentValue()
    end
  end
end

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

M.selectNext = selectNext
M.selectPrevious = selectPrevious
M.incrementCurrentValue = incrementCurrentValue
M.decrementCurrentValue = decrementCurrentValue
M.setConstDirection = setDirection

M.screenOn = htmlScreenOn
M.screenOff = htmlScreenOff
M.screenOnLong = htmlScreenOnLong

return M