--------------------------------------------------------------------------------
--- Globals
--------------------------------------------------------------------------------
Global("gwtOpenConfig", View.openConfig)

-- The Window
Global("gwtAuras", View.AurasWindow)

-- Aura Lines
Global("auraLines", { })
Global("auraData", { })
Global("gwtAuraLine", View.AurasWindow.AuraLine)
Global("gwtScrollableContainer", View.AurasWindow.DockPanel.ScrollableContainer)
--------------------------------------------------------------------------------
--- AURA LINES
--------------------------------------------------------------------------------
function InitializeStandardAuraLine()
  gwtAuraLine.widget:Show(false)
  gwtAuraLine.SetImage = function(self, image)
    self.PictureView.widget:SetBackgroundTexture(image)
  end
  gwtAuraLine.SetText = function(self, text)
    self.NameView:setVal("text", text)
  end
end

function CreateAuraLine()
  local new = { }
  new.widget = mainForm:CreateWidgetByDesc(gwtAuraLine.widget:GetWidgetDesc())
  new.PictureView = { }
  new.PictureView.Values = { }
  new.PictureView.widget = new.widget:GetChildChecked("PictureView", false)
  new.NameView = { }
  new.NameView.Values = { }
  new.NameView.widget = new.widget:GetChildChecked("NameView", false)
  new.NameView.setVal = gwtAuraLine.NameView.setVal
  new.Edit = { }
  new.Edit.widget = new.widget:GetChildChecked("Edit", false)
  new.Edit.widget:SetVal("button_label", L["edit"])
  new.Delete = { }
  new.Delete.widget = new.widget:GetChildChecked("Delete", false)
  new.Delete.widget:SetVal("button_label", L["delete"])
  new.SetImage = gwtAuraLine.SetImage
  new.SetText = gwtAuraLine.SetText
  return new
end

function AddAuraLine(image, text)
  local new = CreateAuraLine()
  new:SetImage(image)
  new:SetText(text)
  table.insert(auraLines, new)
end

function UpdateScrollableContainer()
  gwtScrollableContainer.widget:RemoveItems()
  local index = 0
  for k, v in auraData do
    index = index + 1
    if auraLines[index] == nil then
      auraLines[index] = CreateAuraLine()
    end
    local current = auraLines[index]
    if v.useBuffImage then
      if v.buff or v.debuff then
        local buff = SearchImageByBuffName(v.name)
        if buff then
          current:SetImage(buff.texture)
        else
          current:SetImage(nil)
        end
      elseif v.spellCD then
        current:SetImage(GetSpellTexture(v.name))
      elseif v.itemCD then
        current:SetImage(GetItemTexture(v.name))
      end
    else
      current:SetImage(pictureList[v.pictureIndex].image)
    end
    current:SetText(v.entryname)
    current.Edit.widget:SetName(tostring(k))
    current.Delete.widget:SetName(tostring(k))
    current.name = v.name
    current.pictureIndex = v.pictureIndex
    current.useBuffImage = v.useBuffImage
    current.data = v
    gwtScrollableContainer.widget:PushBack(current.widget)
  end
end

function UpdateImagesInScrollableContainer()
  for k, v in auraLines do
    local data = v.data
    if data.useBuffImage then
      if data.buff or data.debuff then
        local texture = SearchImageByBuffName(data.name)
        if texture then
          v:SetImage(texture)
        else
          v:SetImage(nil)
        end
      elseif data.spellCD then
        v:SetImage(GetSpellTexture(data.name))
      elseif data.itemCD then
        v:SetImage(GetItemTexture(data.name))
      end
    else
      v:SetImage(pictureList[data.pictureIndex].image)
    end
  end
end
--------------------------------------------------------------------------------
--- Reactions
--------------------------------------------------------------------------------
onReaction[gwtOpenConfig.reactionName] = function(params)  
  if gwtAuras.isVisible or gwtSearchWindow.isVisible or gwtSettings.isVisible then
    gwtSettingsPreview:show(false)
    gwtAuras:show(false)
    gwtSearchWindow:show(false)
    gwtSettings:show(false)
  else
    ShowAurasWindow()
  end
end
--------------------------------------------------------------------------------
--- AURA DATA
--------------------------------------------------------------------------------
function UpdateSettings(settings)
  if settings.version == nil then
    settings.version = 0
  end
  if settings.version == 0 then
    settings.showProgressBar = false
    settings.version = 1
  end
end

local IgnoreCleanUpOnTheseFields = { ["groupmembernumber"] = true, defaultTexturePath = true }

function CleanUpSettings(settings, template)
  template.isNew = nil
  for k, v in settings do
    if ((template[k] == nil and settings[k] ~= nil) or template[k] == settings[k] or 
       (common.IsWString(template[k]) and common.IsWString(settings[k]) and EqualsWString(template[k], settings[k]))) and not IgnoreCleanUpOnTheseFields[k] then
      settings[k] = nil
    end
  end
end

function SetDefaultsSettings(settings, template)
  template.isNew = nil
  for k, v in template do
    if settings[k] == nil and v ~= nil then
      settings[k] = template[k]
    end
  end
end

function LoadDefaultTexture(auraData)
  if auraData.defaultTexturePath then
    local buffName = auraData.name
    --LogInfo(buffName, ": ", auraData.defaultTexturePath)
    iconDb.GetTexture(auraData.defaultTexturePath, function(texture)
      if texture then
        auraData.defaultTexture = texture
        UpdateValueByWString(knownBuffs, buffName, texture)
        --LogInfo(buffName, ": ", auraData.defaultTexture, " => ", texture)
      end
      auraData.defaultTexturePath = nil
    end)
  end
end

function Load()
  auraData = userMods.GetAvatarConfigSection ("PowerAurasData") 
  if auraData == nil then
    auraData = { }
  end
  CleanUpAuraData()
  if common.GetTexturePath then -- content of the if is part of the iconDb-Feature => need common.GetTexturePath for this
    for k, v in auraData do
      LoadDefaultTexture(v)    
    end 
  end
  SetDefaultsAuraData()
end

function Save()
  for k, v in auraData do
    if not v.buff and not v.debuff then
      v.defaultTexture = nil
    end
    v.otherruleInstance = nil
  end
  if common.GetTexturePath then -- content of the if is part of the iconDb-Feature => need common.GetTexturePath for this
    for k, v in auraData do
      --LogInfo(v.name, ": ", v.defaultTexturePath, " => ", v.defaultTexture)
      if v.buff or v.debuff then
        if not v.defaultTexturePath then
          if not v.defaultTexture then
            v.defaultTexture = SearchImageByBuffName(v.name)
          end
          if v.defaultTexture then		  
            v.defaultTexturePath = iconDb.GetTexturePath(v.defaultTexture)		  
          end
        elseif not v.defaultTexture then
          v.defaultTexturePath = nil	  
        end
      end
    end
  end
  local cleanedAuraData = CleanUpAuraData(true)  
  userMods.SetAvatarConfigSection("PowerAurasData", cleanedAuraData)
  SetDefaultsAuraData()
  ResetIgnoredBuffs()
end

function CleanUpAuraData(useCopy)
  local cleanupTemplate = CreateEmptyAuraData()
  CreateBasicSettings(cleanupTemplate)
  local items = useCopy and CopyTable(auraData) or auraData
  for k, v in auraData do
    local settings = useCopy and CopyTable(v) or v
    UpdateSettings(settings)
    CleanUpSettings(settings, cleanupTemplate)
    if useCopy then
      items[k] = settings
    end
  end
  return useCopy and items or auraData
end

function SetDefaultsAuraData()
  local cleanupTemplate = CreateEmptyAuraData()
  CreateBasicSettings(cleanupTemplate)
  for k, v in auraData do
    SetDefaultsSettings(v, cleanupTemplate)
  end
end

function CreateEmptyAuraData()
  local new = { }
  new.entryname = common.GetEmptyWString()
  new.isNew = true
  return new
end
--------------------------------------------------------------------------------
--- REACTIONS
--------------------------------------------------------------------------------
onReaction[View.AurasWindow.DockPanel.ButtomButtons.Add.reactionName] = function(params)
  OpenAuraSettings(CreateEmptyAuraData())
end

onReaction[gwtAuraLine.Edit.reactionName] = function(params)
  if params then
    if params.widget then      
      local index = tonumber(params.widget:GetName())
      local data = auraData[index]
      OpenAuraSettings(data)
    end
  end
end

onReaction[gwtAuraLine.Delete.reactionName] = function(params)
  if params then
    if params.widget then
      local index = tonumber(params.widget:GetName())
      local config = auraData[index]
      if config.references then
        for k, v in config.references do
          k:Unregister()
        end
      end
      table.remove(auraData, index)
      gwtAuraPanel:UpdateItems() 
      Save()
      UpdateScrollableContainer()
      UpdateImagesInScrollableContainer()
    end
  end
end
--------------------------------------------------------------------------------
--- Functions
--------------------------------------------------------------------------------
function ShowAurasWindow()
  if currentAuraData ~= nil then
    if not currentAuraData.isAbort then
      if currentAuraData.isNew then
        table.insert(auraData, currentAuraData)
        currentAuraData.isNew = false
      end
      Save()
      UpdateScrollableContainer()	 	  
    end
  end  
  gwtAuras:show(true)
  currentAuraData = nil
  gwtAuraPanel:UpdateItems() 
  gwtAuraPanel.widget:SetFade(1.0)
  UpdateImagesInScrollableContainer()
end

--------------------------------------------------------------------------------
--- INITIALIZATION
--------------------------------------------------------------------------------
function CheckItemId(itemId)
  if itemId then
    local itemInfo = avatar.GetItemInfo(itemId)
    if itemInfo and itemInfo.spellId then
      local spellInfo = avatar.GetSpellInfo(itemInfo.spellId)
    end
  end
end

function InitAuras()  
  gwtAuras:setBackgroundFade(0.8)

  InitializeStandardAuraLine()
  
  Load()
  
  UpdateScrollableContainer()

  gwtAuras:show(false)
  gwtAuras.widget:SetPriority(2000)

  local inventoryItemIds = avatar.GetInventoryItemIds()
  for k, v in inventoryItemIds do
    CheckItemId(v)
  end
  local equipmentItemIds = unit.GetEquipmentItemIds( avatar.GetId(), ITEM_CONT_EQUIPMENT )
  for k, v in equipmentItemIds do
    CheckItemId(v)
  end
end
--------------------------------------------------------------------------------
CallWhenCharacterAvailable(InitAuras)
--------------------------------------------------------------------------------

