---
--- @package   eg4-crank-ui
--- @file      no-activity-timer.lua
--- @brief     Functionality for no activity screen time out.
---
--- @copyright Copyright 2019 Hanover Displays Limited.
--- @license   This program is the confidential and proprietary product of
---            Hanover Displays Limited. Any unauthorised use, reproduction or
---            transfer of this program is strictly prohibited. (Subject to
---            limited distribution and restricted disclosure only.) All
---            rights reserved.
---
---

local WAKE_TIMEOUT = 5000
local MENU_TIMEOUT_DRIVER = 15000        -- Time following display off
local MENU_TIMEOUT_MAINTENANCE = 60000   -- Time following display off

local no_activity_timer_id = nil
local display_state = "off"     -- "wake", "on", "dim", "off"
local dim_hold = {}
local normal_hold = {}

---
--- @brief  Stops the no activity timer
---
function CBStopNoActivityTimer()
  if no_activity_timer_id ~= nil then
    gre.timer_clear_timeout(no_activity_timer_id)
    no_activity_timer_id = nil
  end
end

---
--- @brief Callback on menu time out. 
-- 
-- Stops no activity timeout and transitions to the non activity screen
---
function CBMenuTimeout()
  CBStopNoActivityTimer()
  ScreenTransition(gre.get_value("no_activity_screen"))
end

---
--- @brief  Display off timeout
---
local function CBDisplayDimTimeout()
  CBStopNoActivityTimer()

  if MaintenanceOperatorLoggedIn() then
    no_activity_timer_id = gre.timer_set_timeout(CBMenuTimeout, MENU_TIMEOUT_MAINTENANCE)
  else
    no_activity_timer_id = gre.timer_set_timeout(CBMenuTimeout, MENU_TIMEOUT_DRIVER)
  end

  display_state = "off"
  gre.set_control_attrs("display_off_touch_filter_layer.background", { hidden = 0 } )
  SendEvent("user_display_off")
end

local function StartDimTimeout()
  if next(dim_hold) == nil and next(normal_hold) == nil then
    no_activity_timer_id = gre.timer_set_timeout(CBDisplayDimTimeout, GetDisplayOffTimeout() * 1000)
  end
end

---
--- @brief Time out for display being fully on.
-- 
--  Stop no activity timer, send the "dim" event, start the 
--  dim timeout and change state
---
local function CBDisplayOnTimeout()
  CBStopNoActivityTimer()
  SendEvent("user_display_dim")
  StartDimTimeout()
  display_state = "dim"
end

---
--- @brief  Starts the no activity timer
---
function CBStartNoActivityTimer()
  CBStopNoActivityTimer()
  if display_state == "off" then
    no_activity_timer_id = gre.timer_set_timeout(CBDisplayDimTimeout, WAKE_TIMEOUT)
  else
    if GetDisplayInactivityTimeout() == 0 then
      no_activity_timer_id = gre.timer_set_timeout(CBDisplayDimTimeout, GetDisplayOffTimeout() * 1000)
    else
      no_activity_timer_id = gre.timer_set_timeout(CBDisplayOnTimeout, GetDisplayInactivityTimeout() * 1000)
    end
  end
  gre.set_control_attrs("display_off_touch_filter_layer.background", { hidden = 1 } )

  if display_state == "off" or display_state == "dim" then
    SendEvent("user_display_normal")
  end

  if display_state == "off" then
    display_state = "wake"
  else
    display_state = "normal"
  end
end

---
--- @brief  If it is already running, restarts the no activity timer
---
function CBRestartNoActivityTimer()
  if next(normal_hold) then return end
  if no_activity_timer_id ~= nil or display_state ~= "normal" then
    CBStartNoActivityTimer()
  end
end

---
--- @brief  Activates a source for holding the display at the dim level
--- @param source - source of request (required unique text descriptor)
---
function StartHoldAtDim(source)
  dim_hold[source] = "y"
  if display_state == "dim" then
    -- Stop the dim timeout
    gre.timer_clear_timeout(no_activity_timer_id)
    no_activity_timer_id = nil
  elseif display_state == "off" then
    -- Change to dim
    CBDisplayOnTimeout()
  end
end

---
--- @brief  Cancels a source for holding the display at the dim level
--- @param source - source of request (must match starting descriptor)
---
function CancelHoldAtDim(source)
  dim_hold[source] = nil
  if display_state == "dim" then
    StartDimTimeout()
  end
end

---
--- @brief  Activates a source for holding the display at the normal level
--- @param source - source of request (required unique text descriptor)
---
function StartHoldAtNormal(source)
  normal_hold[source] = "y"
  CBActivateAndHold()
end

---
--- @brief  Cancels a source for holding the display at the normal level
--- @param source - source of request (must match starting descriptor)
---
function CancelHoldAtNormal(source)
  normal_hold[source] = nil
  if next(normal_hold) == nil then
    CBStartNoActivityTimer()
  end
end

---
--- @brief  Activate screen and stop no activity timeout
---
function CBActivateAndHold()
  CBStartNoActivityTimer()
  CBStopNoActivityTimer()
end

-- EOF --
