--[[
Author: Jarth
Filename: MementoBar.lua
]]--

-------------------------------------------------------------------------------------------------
--  Libraries --
-------------------------------------------------------------------------------------------------
local LAM2 = LibStub:GetLibrary("LibAddonMenu-2.0")

-------------------------------------------------------------------------------------------------
--  VARIABLE --
-------------------------------------------------------------------------------------------------
local ADDON_NAME = "MementoBar"
local ADDON_VERSION = 0
local ADDON_MINOR_VERSION = 9.1
local ADDON_AUTHOR = "Jarth"
local ADDON_WEBSITE = ""
local MementoBar = {}
MementoBar.wm = GetWindowManager()
MementoBar.name = ADDON_NAME
MementoBar.MB_Button = {}
MementoBar.Timer = {
  EventName = "TimerUpdate"
}
MementoBar.Fragment = nil
MementoBar.Default = {
  left = CENTER,
  top = CENTER,
  centerColor = { [1] = 0.88, [2] = 0.88, [3] = 0.88, [4] = 0.4 }, -- {red, green, blue, alpha}
  edgeColor = { [1] = 0.57, [2] = 0.57, [3] = 0.57, [4] = 0.6 }, -- {red, green, blue, alpha}
  mementos = {},
  useAccountSettings = true,
  horizontalOrientation = true,
  barDepth = 1,
  hideBarInMenu = true
}

-------------------------------------------------------------------------------------------------
--  FUNCTIONS --
-------------------------------------------------------------------------------------------------
function MementoBar.mbClicked(collectionId)
  if collectionId > 0 and IsCollectibleUnlocked(collectionId) then
    local cooldownRemaining, cooldownDuration = GetCollectibleCooldownAndDuration(collectionId)
    if cooldownRemaining == 0 then
      MementoBar.Activate(collectionId)
    end
  end
end

function MementoBar.initializeButtons()
  local index = 0
  local mbHeight = MB_Frame:GetHeight()
  local mbWidth = MB_Frame:GetWidth()
  --MementoBar.savedVariables.barDepth

  for collectionId in pairs(MementoBar.savedVariables.mementos) do
    if MementoBar.savedVariables.mementos[collectionId].show and IsCollectibleUnlocked(collectionId) then
      if MementoBar.MB_Button[collectionId] == nil then
        MementoBar.MB_Button[collectionId] = WINDOW_MANAGER:CreateControlFromVirtual("MB_Button", MB_FrameBackdrop, "MB_Button", collectionId)
        MementoBar.MB_Button[collectionId]:SetId(collectionId)
      end
      MementoBar.setupButton(collectionId, MementoBar.MB_Button[collectionId])
      MementoBar.MB_Button[collectionId]:SetHidden(false)
      MementoBar.MB_Button[collectionId]:ClearAnchors()
      if MementoBar.savedVariables.horizontalOrientation then
        MementoBar.MB_Button[collectionId]:SetAnchor(TOPLEFT, MB_FrameBackdrop, TOPLEFT, 10+60*(math.floor(index/MementoBar.savedVariables.barDepth)), 10+60*(index % MementoBar.savedVariables.barDepth))
      else
        MementoBar.MB_Button[collectionId]:SetAnchor(TOPLEFT, MB_FrameBackdrop, TOPLEFT, 10+60*(index % MementoBar.savedVariables.barDepth), 10+60*(math.floor(index/MementoBar.savedVariables.barDepth)))
      end
      index = index + 1
    else
      if MementoBar.MB_Button[collectionId] then
        MementoBar.MB_Button[collectionId]:SetHidden(true)
      end
    end
  end
end

function MementoBar.setFragmentBehaviour(menuOpen)
  if MementoBar.Fragment == nil then
    MementoBar.Fragment = ZO_HUDFadeSceneFragment:New( MB_Frame )
  end

  if MementoBar.savedVariables.hideBarInMenu then
    MementoBar.addControlToFrame(menuOpen)
  else
    MementoBar.removeControlToFrame(menuOpen)
  end
end

function MementoBar.addControlToFrame(menuOpen)
  if menuOpen then
    MB_Frame:SetHidden(true)
  end
  SCENE_MANAGER:GetScene('hud'):AddFragment(MementoBar.Fragment)
  SCENE_MANAGER:GetScene('hudui'):AddFragment(MementoBar.Fragment)
end

function MementoBar.removeControlToFrame(menuOpen)
  if menuOpen then
    MB_Frame:SetHidden(false)
  end

  SCENE_MANAGER:GetScene('hud'):RemoveFragment(MementoBar.Fragment)
  SCENE_MANAGER:GetScene('hudui'):RemoveFragment(MementoBar.Fragment)
end

function MementoBar.setButtonFrameWidth()
  local mbBtnHeight = 60
  local mbBtnWidth = 60
  local mbCount = 0
  local mbHeight = 0
  local mbWidth = 0

  for collection in pairs(MementoBar.savedVariables.mementos) do
    if MementoBar.savedVariables.mementos[collection].show then
      mbCount = mbCount + 1
    end
  end

  mbDepth = math.ceil(mbCount / MementoBar.savedVariables.barDepth)
  mbHeight = MementoBar.savedVariables.horizontalOrientation and mbBtnHeight * MementoBar.savedVariables.barDepth or mbBtnHeight * mbDepth
  mbWidth = MementoBar.savedVariables.horizontalOrientation and mbBtnWidth * mbDepth or mbBtnWidth * MementoBar.savedVariables.barDepth

  MB_Frame:SetHidden(mbCount == 0)
  MB_FrameBackdrop:SetHidden(mbCount == 0)
  MB_Frame:SetHeight(mbHeight)
  MB_FrameBackdrop:SetHeight(mbHeight)
  MB_Frame:SetWidth(mbWidth)
  MB_FrameBackdrop:SetWidth(mbWidth)
end

function MementoBar.setupButton(collectionId, MB_Button)
  local MB_ButtonTexture = MementoBar.wm:GetControlByName("MB_Button"..collectionId.."Texture")
  if MB_ButtonTexture and MementoBar.savedVariables.mementos[collectionId].collectibleIcon then
    MB_ButtonTexture:SetTexture(MementoBar.savedVariables.mementos[collectionId].collectibleIcon)
    MB_Button:SetHandler("OnClicked", function(self) MementoBar.mbClicked(MB_Button:GetId()) end)
  end
end

function MementoBar.mbRestorePosition()
  local top = MementoBar.savedVariables.top
  local left = MementoBar.savedVariables.left
  MB_Frame:ClearAnchors()
  MB_Frame:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, left, top)
end

-- Global accessed function, allowing OnMoveStop to find the function.
function MementoBar_OnMoveStop()
  MementoBar.savedVariables.top = MB_Frame:GetTop()
  MementoBar.savedVariables.left = MB_Frame:GetLeft()
end

function MementoBar.RestorePanel()
  MementoBar.setFragmentBehaviour()

  MementoBar.setButtonFrameWidth()

  MementoBar.initializeButtons()

  MementoBar.mbRestorePosition()
end

function MementoBar.GetVersion(showMinor)
  if showMinor == false or ADDON_MINOR_VERSION == nil  then
    return tostring(ADDON_VERSION)
  end
    return tostring(ADDON_VERSION) .. "." .. tostring(ADDON_MINOR_VERSION)
end

function MementoBar.Activate(collectionId)
  local start = GetTimeStamp()
  local cooldownRemaining, cooldownDuration = GetCollectibleCooldownAndDuration(collectionId)
  --d("Activate",cooldownRemaining, cooldownDuration, collectionId, start)

  local function Update(eventId)
    cooldownRemaining, cooldownDuration = GetCollectibleCooldownAndDuration(collectionId)
    if cooldownRemaining > 0 then
      MementoBar.UpdateLabel(cooldownRemaining)
    elseif (GetTimeStamp() < (start + math.floor(cooldownDuration/1000)))  then
      MementoBar.UpdateLabel(cooldownDuration)
    else
      MementoBar.UpdateLabel("")
      EVENT_MANAGER:UnregisterForEvent(MementoBar.name, EVENT_ABILITY_COOLDOWN_UPDATED)
    end
  end

  if IsCollectibleUsable(collectionId) then
    UseCollectible(collectionId)
    EVENT_MANAGER:RegisterForEvent(MementoBar.name, EVENT_ABILITY_COOLDOWN_UPDATED, Update)
  end
end

function MementoBar.UpdateLabel(remaining)
  if type(remaining) == "number" and remaining > 0 then
    remaining = string.format("%." .. 1 .. "f" .. "s", (math.floor(remaining / 100)/10))
  end
  for collectionId in pairs(MementoBar.savedVariables.mementos) do
    local MB_ButtonTimer = MementoBar.wm:GetControlByName("MB_Button"..collectionId.."Timer")
    if MB_ButtonTimer and MementoBar.savedVariables.mementos[collectionId].show then
      MB_ButtonTimer:SetText(remaining)
    end
  end
end

-------------------------------------------------------------------------------------------------
--  Menu Functions --
-------------------------------------------------------------------------------------------------
function MementoBar.CreateSettingsWindow()
  local mementTopLevelIndex = 7
  local catName, catNumSubCat, catNumCollectibles, catNumUnlocked, catTotal, catHidesLocked  = GetCollectibleCategoryInfo(mementTopLevelIndex)
  --d(catName, catNumSubCat, catNumCollectibles, catNumUnlocked, catTotal, catHidesLocked)

	local panelData = {
		type = "panel",
		name = "Memento Bar",
		displayName = "Memento Bar",
		author = ADDON_AUTHOR,
    version = MementoBar.GetVersion(true),
		slashCommand = "/mb",
		registerForRefresh = true,
		registerForDefaults = true,
	}
	local cntrlOptionsPanel = LAM2:RegisterAddonPanel(ADDON_NAME, panelData)

	local optionsData = {
		[1] = {
			type = "header",
			name = "Memento Bar Settings"
		},
		[2] = {
			type = "description",
			text = "Here you can adjust the memento bar settings. Including what icons to show, and color of the bar."
		},
		[3] = {
			type = "checkbox",
			name = "Use account settings",
			tooltip = "When ON the account settings will be used. When OFF character settings will be used.",
			default = MementoBar.Default.useAccountSettings,
			getFunc = function() return MementoBar.savedVariables.useAccountSettings end,
			setFunc = function(newValue)
        --Apply value to existing variable
			  MementoBar.savedVariables.useAccountSettings = newValue;
			  if newValue then
				  MementoBar.savedVariables = ZO_SavedVars:NewAccountWide("MementoBar_Account", ADDON_VERSION, nil, MementoBar.Default)
			  else
				  MementoBar.savedVariables = ZO_SavedVars:New("MementoBar_Character", ADDON_VERSION, nil, MementoBar.Default)
			  end
        --Apply value to new variable
			  MementoBar.savedVariables.useAccountSettings = newValue;
			  MB_FrameBackdrop:SetCenterColor(unpack(MementoBar.savedVariables.centerColor))
			  MB_FrameBackdrop:SetEdgeColor(unpack(MementoBar.savedVariables.edgeColor))
			  MementoBar.RestorePanel()
			end,
		},
		[4] = {
			type = "checkbox",
			name = "Bar orientation horizontal",
			tooltip = "When ON the bar will orientate horizontally.",
			default = MementoBar.Default.horizontalOrientation,
			getFunc = function() return MementoBar.savedVariables.horizontalOrientation end,
      setFunc = function(newValue)
        MementoBar.savedVariables.horizontalOrientation = newValue
        MementoBar.RestorePanel()
			end,
		},
		[5] = {
			type = "checkbox",
			name = "Hide bar in menu",
			tooltip = "When ON the bar will hide when a menu is opened.",
			default = MementoBar.Default.hideBarInMenu,
			getFunc = function() return MementoBar.savedVariables.hideBarInMenu end,
      setFunc = function(newValue)
        MementoBar.savedVariables.hideBarInMenu = newValue
        MementoBar.setFragmentBehaviour(true)
			end,
		},
		[6] = {
			type = "submenu",
			name = "Colors",
			tooltip = "Allows you to change colors.",
			controls = {
			[1] = {
			  type = "description",
			  text = "Here you can adjust the colors."
			},
			[2] = {
			  type = "colorpicker",
			  name = "Backdrop Color",
			  default = MementoBar.Default.centerColor,
			  tooltip = "Changes the color of the background.",
			  getFunc = function() return unpack( MementoBar.savedVariables.centerColor ) end,
			  setFunc = function(r,g,b,a)
          MementoBar.savedVariables.centerColor = {r,g,b,a}
          MB_FrameBackdrop:SetCenterColor(r,g,b,a)
			  end,
			width = "half"
			},
			[3] = {
				type = "colorpicker",
				name = "Frame Color",
				default = MementoBar.Default.edgeColor,
				tooltip = "Changes the color of the frame.",
				getFunc = function() return unpack( MementoBar.savedVariables.edgeColor ) end,
				setFunc = function(r,g,b,a)
					MementoBar.savedVariables.edgeColor = {r,g,b,a}
					MB_FrameBackdrop:SetEdgeColor(r,g,b,a)
				end,
				width = "half"
				}
			},
    },
    [7] = {
      type = "submenu",
      name = catName .. " (Total: " .. catTotal .. " Unlocked: ".. catNumUnlocked .. ")",
      tooltip = "Choose what memento's you want on the bar.",
      controls = {
        [1] = {
          type = "slider",
          name = "Choose bar depth (number of rows/columns)", -- or string id or function returning a string
          default = MementoBar.Default.barDepth,
          getFunc = function() return MementoBar.savedVariables.barDepth end,
          setFunc = function(value)
            MementoBar.savedVariables.barDepth = value
            MementoBar.RestorePanel()
          end,
          min = 1,
          max = catNumUnlocked
        },
        [2] = {
          type = "description",
          text = "Choose what memento's you want enabled."
        }
      }
    }
  }

  for i = 1, catTotal do
    local index = i + 1
    local collectibleId = GetCollectibleId(mementTopLevelIndex, nil, i)
    --** _Returns:_ *string* _name_, *string* _description_, *textureName* _icon_, *textureName* _deprecatedLockedIcon_, *bool* _unlocked_, *bool* _purchasable_, *bool* _isActive_, *[CollectibleCategoryType|#CollectibleCategoryType]* _categoryType_, *string* _hint_, *bool* _isPlaceholder_
    local collectibleName, collectibleDescription, collectibleIcon, collectibleLockedIcon, collectibleUnlocked, collectiblePurchasable, collectibleIsActive, collectibleCollectibleCategoryType, collectibleHint, collectibleIsPlaceholder = GetCollectibleInfo(collectibleId)
    --d('Start', collectibleName, collectibleDescription, collectibleIcon, collectibleLockedIcon, collectibleUnlocked, collectiblePurchasable, collectibleIsActive, collectibleCollectibleCategoryType, collectibleHint, collectibleIsPlaceholder, 'End')

    local line = {
      type = "checkbox",
      name = "Show " .. collectibleName,
      tooltip = collectibleDescription,
      --tooltip = "When ON the vendor button will be visible. When OFF the vendor button will not be visible (disabled if locked for the account).",
      default = false,
      disabled = not collectibleUnlocked,
      getFunc = function()
        if MementoBar.savedVariables.mementos[collectibleId] == nil or not MementoBar.savedVariables.mementos[collectibleId].show then
          return false
        else
          return true
        end
      end,
      setFunc = function(newValue)
        if MementoBar.savedVariables.mementos[collectibleId] == nil then
          MementoBar.savedVariables.mementos[collectibleId] = {
            show = newValue,
            collectibleIcon = collectibleIcon
          }
        else
          MementoBar.savedVariables.mementos[collectibleId].show = newValue
          MementoBar.savedVariables.mementos[collectibleId].collectibleIcon = collectibleIcon
        end

        MementoBar.RestorePanel()
      end
    }
    table.insert(optionsData[7].controls, index, line)
  end

	LAM2:RegisterOptionControls(ADDON_NAME, optionsData)
end

function MementoBar:Initialize()
  -- Load saved values..
	MementoBar.savedVariables = ZO_SavedVars:New("MementoBar_Character", ADDON_VERSION, nil, MementoBar.Default)
  if MementoBar.savedVariables.useAccountSettings then
    MementoBar.savedVariables = ZO_SavedVars:NewAccountWide("MementoBar_Account", ADDON_VERSION, nil, MementoBar.Default)
  end

  MementoBar.RestorePanel()
  -- Create menu variables.
  MementoBar.CreateSettingsWindow()
  MB_FrameBackdrop:SetCenterColor(unpack(MementoBar.savedVariables.centerColor))
  MB_FrameBackdrop:SetEdgeColor(unpack(MementoBar.savedVariables.edgeColor))
  -- ToDo - End.
  EVENT_MANAGER:UnregisterForEvent(MementoBar.name, EVENT_ADD_ON_LOADED)
end

-- Then we create an event handler function which will be called when the "addon loaded" event
-- occurs. We'll use this to initialize our addon after all of its resources are fully loaded.
function MementoBar.OnAddOnLoaded(event, addonName)
  -- The event fires each time *any* addon loads - but we only care about when our own addon loads.
  if addonName == MementoBar.name then
    MementoBar:Initialize()
  end
end

-- Load Event
-- We unregistered this at the end of the loadCC function for optimization.
-- Here we register it (after all the functions).
-- EVENT_MANAGER:RegisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED, MementoBar.mbLoad)
EVENT_MANAGER:RegisterForEvent(MementoBar.name, EVENT_ADD_ON_LOADED, MementoBar.OnAddOnLoaded)
-- EVENT_MANAGER:RegisterForEvent("MementoBar Click", EVENT_GLOBAL_MOUSE_DOWN, MementoBar.mbClicked) -- Edit by Mitsarugi, addon wont work without this line of code