-- AI Research Grid Addon for Elder Scrolls Online
-- Author: Stormknight/LCAmethyst
-- "All" and "Relative"  functionality by His Dad
-- Dwemer Motif by rkuhnjr
-- Dwemer Motif By garkin
-- French Translation by Motsah
-- Fixes by mpavlinsky
-- Close on Esc code by Wandamey
-- Glass, Xivkyn, and Ancient Orc added in by Scinutz

local _
AIRG = {}

AIRG.name = "AIResearchGrid"
AIRG.version = "3.3.6"
AIRG.initialised = false
AIRG.processing = false
AIRG.all = " #ALL"  -- Default displayname for Virtual character, overrwritten by Localised version
AIRG.ShowRelative = false  -- State of Button
AIRG.relative= {}
AIRG.L = {}   -- declare language strings

-- Set-up the defaults options for saved variables.
AIRG.defaults = {
    data        = {},
    styles      = {},
    showMotifs = true,
}


function AIRG.PlayerActivated()
        -- somehow somewhere it sometimes happens that the data is not correct completely for whatever reason
        -- so we force a reload of the current character data when we are actually loaded into the world.
	AIRG.PopulateMatrix()
	AIRG.PopulateStyleData()
	AIRG.DisplayStyles()
	AIRG.PopulateAll()  -- do last

end

function AIRG.ToggleMainWindow()
    if (AIResearchGrid:IsHidden()) then
        AIRG.OnCraftSelected()              -- Redisplay data for the current profession
    end

	SCENE_MANAGER:ToggleTopLevel(AIResearchGrid)	-- Thanks Wandamey
end -- AIRG.ToggleMainWindow

-- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_STARTED
-- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
function AIRG.ResearchStarted(eventCode, craftingSkillType, researchLineIndex, traitIndex)
    AIRG.PopulateMatrix()
    AIRG.PopulateAll()
    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
end -- AIRG.ResearchStarted

-- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED
-- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
function AIRG.ResearchCompleted()
    AIRG.PopulateMatrix()
    AIRG.PopulateAll()
    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
end -- AIRG.ResearchEnded

function AIRG.StyleLearned(eventCode, styleIndex)
    AIRG.PopulateStyleData()
    AIRG.DisplayStyles()
    AIRG.PopulateAll()
end -- AIRG.StyleLearned

-- Invoked from AIRG.Initialise but lengthy so in it's own function to not clutter Initialise
function AIRG.initUI()
    -- Some local variable declaration
    local i, j, zz, yy      -- used in for loops
    local thisTrait, tType, tDesc, rowNum, charName
    -- Initialise a table to hold all the lua generated components
    AIRG.UI = {}
    -- Set the main window title
    AIRG.UI.WindowTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowTitle", AIResearchGrid, CT_LABEL)
    AIRG.UI.WindowTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 0)
    AIRG.UI.WindowTitle:SetFont("ZoFontAnnounceMedium")
    AIRG.UI.WindowTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
    AIRG.UI.WindowTitle:SetText("|c8080ffAI|r RESEARCH GRID")
    -- Set the main window subtitle
    AIRG.UI.WindowSubTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowSubTitle", AIResearchGrid, CT_LABEL)
    AIRG.UI.WindowSubTitle:SetAnchor(LEFT, AIRG.UI.WindowTitle, RIGHT, 10, 0)
    AIRG.UI.WindowSubTitle:SetFont("ZoFontAnnounceMedium")
    AIRG.UI.WindowSubTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
    AIRG.UI.WindowSubTitle:SetColor(0, 1, 0, 1);    -- green
    AIRG.UI.WindowSubTitle:SetText("")
    -- Nice little line under the main title
    -- ## Check is htis showing right?
    AIRG.UI.TopDivider = WINDOW_MANAGER:CreateControl("AIResearchGridTopDivider", AIResearchGrid, CT_TEXTURE)
    AIRG.UI.TopDivider:SetDimensions(790, 5)
    AIRG.UI.TopDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 25, 32)
    AIRG.UI.TopDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
    -- Nice little line under the grid
    AIRG.UI.BottomDivider = WINDOW_MANAGER:CreateControl("AIResearchGridBottomDivider", AIResearchGrid, CT_TEXTURE)
    AIRG.UI.BottomDivider:SetDimensions(790, 5)
    AIRG.UI.BottomDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 25, 636)
    AIRG.UI.BottomDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
    AIRG.UI.BottomDivider:SetHidden(not AIRG.vars.showMotifs)
    -- CREATE BUTTON FOR CLOSE ADDON AT TOP_RIGHT
    AIRG.UI.btnCloseAddonFrame = WINDOW_MANAGER:CreateControl("AIResearchGridButtonCloseAddon", AIResearchGrid, CT_BUTTON)
    AIRG.UI.btnCloseAddonFrame:SetDimensions(28, 28)
    AIRG.UI.btnCloseAddonFrame:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, 5 , 0)
    AIRG.UI.btnCloseAddonFrame:SetState(BSTATE_NORMAL)
    AIRG.UI.btnCloseAddonFrame:SetMouseOverBlendMode(0)
--    AIRG.UI.btnCloseAddonFrame:SetHidden(false)
    AIRG.UI.btnCloseAddonFrame:SetEnabled(true)
--    AIRG.UI.btnCloseAddonFrame:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
    AIRG.UI.btnCloseAddonFrame:SetNormalTexture("/esoui/art/buttons/clearslot_down.dds")
    AIRG.UI.btnCloseAddonFrame:SetMouseOverTexture("/esoui/art/buttons/clearslot_up.dds")
    AIRG.UI.btnCloseAddonFrame:SetHandler("OnClicked", function(self) AIRG.ToggleMainWindow() end)

    -- CREATE the DROPDOWN BOX for CHARACTER SELECT
    -- Uses code based on example from Seerah
    AIRG.UI.charDropdown = WINDOW_MANAGER:CreateControlFromVirtual("AIResearchGridDropdownCharacter", AIResearchGrid, "ZO_StatsDropdownRow")
    AIRG.UI.charDropdown:SetWidth(205) -- Defaults to 607!!!
    AIRG.UI.charDropdown:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, -32, 0)
    AIRG.UI.charDropdown:GetNamedChild("Dropdown"):SetWidth(200)
    AIRG.UI.charDropdown.dropdown:SetSelectedItem(AIRG.curCharacter)  -- Set the current character as selected
    local function OnItemSelect(_, choiceText, choice)  --this is the callback function for when an item gets selected in the dropdown
        AIRG.OnCharacterSelect(choiceText)
    end
    for charName, _ in pairs(AIRG.vars.data) do
        local entry = AIRG.UI.charDropdown.dropdown:CreateItemEntry(charName, OnItemSelect)
        AIRG.UI.charDropdown.dropdown:AddItem(entry)
    end
    -- CREATE BUTTON FOR "Relative to" AT TOP_RIGHT
    AIRG.UI.btnUpdateOther = WINDOW_MANAGER:CreateControlFromVirtual("AIResearchGridButtonUpdateOther", AIResearchGrid, "ZO_DefaultButton")
	--Attempt to adjust button size to content, but units are different. May not be fixable. leave for meantime.
    local textlen = 0
    if string.len(AIRG.L["btnRelativeOn"]) > string.len(AIRG.L["btnRelativeOff"])
    then textlen = string.len(AIRG.L["btnRelativeOn"])
    else textlen = string.len(AIRG.L["btnRelativeOff"])
    end

    AIRG.UI.btnUpdateOther:SetDimensions(140+textlen, 30)
    AIRG.UI.btnUpdateOther:SetAnchor(RIGHT, AIRG.UI.charDropdown, LEFT, 0, 0)
    AIRG.UI.btnUpdateOther:SetState(BSTATE_NORMAL)
    AIRG.UI.btnUpdateOther:SetMouseOverBlendMode(0)
--    AIRG.UI.btnUpdateOther:SetNormalTexture("/esoui/art/icons/ability_tradecraft_008.dds")
    AIRG.UI.btnUpdateOther:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
    AIRG.UI.btnUpdateOther:SetClickSound("Click")
    AIRG.UI.btnUpdateOther:SetDisabledFontColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
    AIRG.UI.btnUpdateOther:SetFont("ZoFontGame")
    AIRG.UI.btnUpdateOther:SetText(AIRG.L["btnRelativeOff"])
    AIRG.UI.btnUpdateOther:SetEnabled(false)  -- starts pointing to current character, which can't use this
    AIRG.UI.btnUpdateOther:SetHidden(false)
-- enabled at end of function
    AIRG.UI.btnUpdateOther:SetHandler("OnClicked",
      function(self)
                    AIRG.ShowRelative = not AIRG.ShowRelative
                    if AIRG.ShowRelative
                       then  self:SetText(AIRG.L["btnRelativeOn"]) -- Lime green
  --                     else  self:SetText(AIRG.btnUpdateOtherText1 )
                        else  self:SetText(AIRG.L["btnRelativeOff"])
                    end
                    AIRG.OnCraftSelected() --redisplay
         end)
  --  The following have caused bugs to be reported, that I can't duplicate. As there is no tooltip text, disable it entirely.
  --  AIRG.UI.btnUpdateOther:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
  --  AIRG.UI.btnUpdateOther:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)


    AIRG.UI.btnUpdateOther:SetMouseEnabled(true)

    -- CREATE BUTTON FOR PROFESSION: BLACKSMITHING
    AIRG.UI.btnBlacksmithing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonBlacksmithing", AIResearchGrid, CT_BUTTON)
    AIRG.UI.btnBlacksmithing:SetDimensions(48, 48)
    AIRG.UI.btnBlacksmithing:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 8 , 44)
    AIRG.UI.btnBlacksmithing:SetState(BSTATE_NORMAL)
    AIRG.UI.btnBlacksmithing:SetMouseOverBlendMode(0)
    AIRG.UI.btnBlacksmithing:SetHidden(false)
    AIRG.UI.btnBlacksmithing:SetEnabled(true)
    AIRG.UI.btnBlacksmithing:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
    AIRG.UI.btnBlacksmithing:SetNormalTexture("/esoui/art/icons/ability_smith_007.dds")
    AIRG.UI.btnBlacksmithing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
    AIRG.UI.btnBlacksmithing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_BLACKSMITHING) end)
    -- CREATE BUTTON FOR PROFESSION: WOODWORKING
    AIRG.UI.btnWoodworking = WINDOW_MANAGER:CreateControl("AIResearchGridButtonWoodworking", AIResearchGrid, CT_BUTTON)
    AIRG.UI.btnWoodworking:SetDimensions(48, 48)
    AIRG.UI.btnWoodworking:SetAnchor(TOPLEFT, AIRG.UI.btnBlacksmithing, TOPRIGHT, 12 , 0)
    AIRG.UI.btnWoodworking:SetState(BSTATE_NORMAL)
    AIRG.UI.btnWoodworking:SetMouseOverBlendMode(0)
    AIRG.UI.btnWoodworking:SetHidden(false)
    AIRG.UI.btnWoodworking:SetEnabled(true)
    AIRG.UI.btnWoodworking:SetClickSound(SOUNDS.BLACKSMITH_EXTRACTED_BOOSTER)
    AIRG.UI.btnWoodworking:SetNormalTexture("/esoui/art/icons/ability_tradecraft_009.dds")
    AIRG.UI.btnWoodworking:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
    AIRG.UI.btnWoodworking:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_WOODWORKING) end)
    -- CREATE BUTTON FOR PROFESSION: CLOTHING
    AIRG.UI.btnClothing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonClothing", AIResearchGrid, CT_BUTTON)
    AIRG.UI.btnClothing:SetDimensions(48, 48)
    AIRG.UI.btnClothing:SetAnchor(TOPLEFT, AIRG.UI.btnWoodworking, TOPRIGHT, 12 , 0)
    AIRG.UI.btnClothing:SetState(BSTATE_NORMAL)
    AIRG.UI.btnClothing:SetMouseOverBlendMode(0)
    AIRG.UI.btnClothing:SetHidden(false)
    AIRG.UI.btnClothing:SetEnabled(true)
    AIRG.UI.btnClothing:SetClickSound(SOUNDS.CLOTHIER_EXTRACTED_BOOSTER)
    AIRG.UI.btnClothing:SetNormalTexture("/esoui/art/icons/ability_tradecraft_008.dds")
    AIRG.UI.btnClothing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
    AIRG.UI.btnClothing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_CLOTHIER) end)

    -- BUILD THE TRAIT LABELS ON THE LEFT-SIDE using built-in language strings
    AIRG.UI.rowLabels = {}
    for thisTrait, j in pairs(AIRG.gridTraits) do
        AIRG.UI.rowLabels[j] = WINDOW_MANAGER:CreateControl("AIResearchGridRowLabel" .. tostring(j), AIResearchGrid, CT_LABEL)
        AIRG.UI.rowLabels[j]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 28*j + 70)
        AIRG.UI.rowLabels[j]:SetText(GetString("SI_ITEMTRAITTYPE",thisTrait))       -- This is the text displayed on the screen as it's a label
        AIRG.UI.rowLabels[j]:SetDimensions(180, 24)
        AIRG.UI.rowLabels[j]:SetFont("ZoFontGame")
        AIRG.UI.rowLabels[j]:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
        AIRG.UI.rowLabels[j]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
        AIRG.UI.rowLabels[j]:SetMouseEnabled(true)
        AIRG.UI.rowLabels[j]:SetHandler("OnMouseEnter", function (self)
                            ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
                        end)
        AIRG.UI.rowLabels[j]:SetHandler("OnMouseExit", function (self)
                            ZO_Tooltips_HideTextTooltip()
                        end)
    end
    -- Now add tooltip text to the row labels.
    -- The tooltip functionality is automatic as part of the label control.
    for j = 1, 9 do
        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,1,j) -- weapons
        rowNum = AIRG.gridTraits[tType]
        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,9,j) -- armour
        rowNum = AIRG.gridTraits[tType]
        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
    end
    -- BUILD THE COLUMNS & GRID
    -- Determine the maximum number of item types across all three professions. This is currently always 14
    AIRG.maxColumns= math.max(GetNumSmithingResearchLines(CRAFTING_TYPE_BLACKSMITHING),
            GetNumSmithingResearchLines(CRAFTING_TYPE_CLOTHIER),
            GetNumSmithingResearchLines(CRAFTING_TYPE_WOODWORKING))
    AIRG.UI.columnButtons = {}
    AIRG.UI.gridButtons = {}
    AIRG.UI.columnFooters = {}
    for i = 1, AIRG.maxColumns do
        -- BUILD THE COLUMN BUTTONS
        AIRG.UI.columnButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridHeaderButton" .. tostring(i), AIResearchGrid, CT_BUTTON)
        AIRG.UI.columnButtons[i]:SetDimensions(36, 36)
        AIRG.UI.columnButtons[i]:SetState(BSTATE_NORMAL)
        AIRG.UI.columnButtons[i]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 40*i + 150, 55)
        AIRG.UI.columnButtons[i]:SetHidden(true)
        AIRG.UI.columnButtons[i]:SetEnabled(true)
        AIRG.UI.columnButtons[i]:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
        AIRG.UI.columnButtons[i].text = i	-- placeholder
        AIRG.UI.columnButtons[i]:SetHandler("OnMouseEnter", function (self)
                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.text)
                                            end)
        AIRG.UI.columnButtons[i]:SetHandler("OnMouseExit", function (self)
                                                ZO_Tooltips_HideTextTooltip()
                                            end)
        -- BUILD THE GRID
        -- There are a total of 18 traits possible. 9 armour and 9 weapon (Infused, Training and Nirnhoned on both)
        AIRG.UI.gridButtons[i] = {}
        for j = 1, 18 do
            AIRG.UI.gridButtons[i][j] = WINDOW_MANAGER:CreateControl("AIResearchGridGridButton" .. tostring(i) .. "x" .. tostring(j), AIResearchGrid, CT_TEXTURE)
            AIRG.UI.gridButtons[i][j]:SetDimensions(24, 24)
            AIRG.UI.gridButtons[i][j]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 28*j -20)
            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")  -- little square box
            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
            AIRG.UI.gridButtons[i][j]:SetHidden(false)
            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)
            -- Following tooltip code uses ideas contributed by Krysstof
            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseEnter", function (self)
			            --   if (self.tooltipText > 0) then      -- Check the item is being researched and has a timestamp
                        if (self.Known > 0) then      -- Check the item is being researched and has a timestamp
					        local tRemaining = tonumber(self.Known) - GetTimeStamp()
                            local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
							ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
    						-- loop with "registerforupdate" once per second
    						EVENT_MANAGER:RegisterForUpdate(self.name, 1000, function()
    						        local tRemaining = tonumber(self.Known) - GetTimeStamp()
                                    local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
									ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
    						    end)
						else
							ZO_Tooltips_ShowTextTooltip(self, RIGHT, self.tooltipText)
    				    end
					end)
            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseExit", function (self)
						-- unregister the update event or it keeps on displaying
						EVENT_MANAGER:UnregisterForUpdate(self.name)
						ZO_Tooltips_HideTextTooltip()
					end)
        end
        -- BUILD THE COLUMN FOOTERS
        AIRG.UI.columnFooters[i] = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterLabel" .. tostring(i), AIResearchGrid, CT_LABEL)
        AIRG.UI.columnFooters[i]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 516)
        AIRG.UI.columnFooters[i]:SetDimensions(36, 24)
        AIRG.UI.columnFooters[i]:SetFont("ZoFontGame")
        AIRG.UI.columnFooters[i]:SetHorizontalAlignment(TEXT_ALIGN_CENTER)
        AIRG.UI.columnFooters[i]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
        AIRG.UI.columnFooters[i]:SetColor(1, 1, 0.4, 1);    -- faded yellow
    end
    -- BUILD LABEL FOR COLUMN FOOTER "TRAIT LINE"
    AIRG.UI.columnFooterTitle = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterTitleLabel", AIResearchGrid, CT_LABEL)
    AIRG.UI.columnFooterTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 606)
    AIRG.UI.columnFooterTitle:SetDimensions(180, 24)
    AIRG.UI.columnFooterTitle:SetFont("ZoFontGame")
    AIRG.UI.columnFooterTitle:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
    AIRG.UI.columnFooterTitle:SetVerticalAlignment(TEXT_ALIGN_CENTER)
    AIRG.UI.columnFooterTitle:SetColor(1, 1, 0.4, 1);       -- faded yellow
--    AIRG.UI.columnFooterTitle:SetText(GetString(SI_SMITHING_RESEARCH_LINE_HEADER))
    AIRG.UI.columnFooterTitle:SetText(GetString(SI_CRAFTING_COMPONENT_TOOLTIP_TRAITS))   -- "Traits"

    -- BUILD THE MOTIF ICONS ACROSS THE BOTTOM
    -- Note that for now, we're just setting up 15 icons and stuff is configured manually
    -- but we can fix it later. It's not like it's going to have an overhead on processing. :)
    -- It's set-up inside a container frame to make hiding or showing the whole lot simpler.
    AIRG.UI.motifSection = WINDOW_MANAGER:CreateControl("AIResearchMotifSection", AIResearchGrid, CT_CONTROL)
    AIRG.UI.motifSection:SetDimensions(790, 50)
    AIRG.UI.motifSection:SetAnchor(BOTTOMLEFT, AIResearchGrid, BOTTOMLEFT, -110, 0)
    AIRG.UI.motifSection:SetHidden(not AIRG.vars.showMotifs)
    AIResearchGrid:SetHeight(AIRG.vars.showMotifs and 706 or 636)
    AIRG.UI.motifButtons = {}
    for i = 1, 18 do

        AIRG.UI.motifButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridMotifButton" .. tostring(i), AIRG.UI.motifSection, CT_TEXTURE)
        AIRG.UI.motifButtons[i]:SetDimensions(40, 40)
        AIRG.UI.motifButtons[i]:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, 41*i + 124, 0)
        AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
        AIRG.UI.motifButtons[i]:SetMouseEnabled(true)
        j = AIRG.styleLookupValue[i]
        tDesc ,_,_,_,_ = GetSmithingStyleItemInfo( AIRG.styleLookupItem[i] )
        AIRG.UI.motifButtons[i].tooltipText = zo_strformat("<<t:1>>\n<<t:2>>", GetString("SI_ITEMSTYLE",j), tDesc)
        AIRG.UI.motifButtons[i]:SetHandler("OnMouseEnter", function (self)
                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
                                            end)
        AIRG.UI.motifButtons[i]:SetHandler("OnMouseExit", function (self)
                                                ZO_Tooltips_HideTextTooltip()
                                            end)
    end
    -- BUILD LABEL FOR STYLES
    AIRG.UI.StyleLabel = WINDOW_MANAGER:CreateControl("AIResearchStylelabel", AIRG.UI.motifSection, CT_LABEL)
    AIRG.UI.StyleLabel:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, 5, 6)
    AIRG.UI.StyleLabel:SetText(GetString(SI_SMITHING_HEADER_STYLE))
    AIRG.UI.StyleLabel:SetDimensions(150, 24)
    AIRG.UI.StyleLabel:SetFont("ZoFontGame")
    AIRG.UI.StyleLabel:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)


end -- AIRG.initUI

-- User has clicked on one of the profession buttons
-- or we just want to refresh the display with current data
function AIRG.OnCraftSelected(_,thisCraft)
    if (thisCraft == nil) then
        if (AIRG.curCraft == nil) then
            return
        else
            thisCraft = AIRG.curCraft
        end
    end



    AIRG.UI.WindowSubTitle:SetText(AIRG.craftNames[thisCraft])
    local i,j,busy

    local tType,tDesc,tKnown,tRemain,rowNum,traitCount,alltraits, tooltiptext
    local maxLines = GetNumSmithingResearchLines(thisCraft) -- the number of columns for this profession
    AIRG.curCraft = thisCraft
	alltraits = 0

    for i = 1, AIRG.maxColumns do
        busy = false
        -- "blank" the grid
        for j = 1, 18 do
            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")
            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)    -- effectively disable tooltip for this grid item.
        end
        if (i > maxLines) then
            AIRG.UI.columnButtons[i]:SetHidden(true)
            AIRG.UI.columnFooters[i]:SetText("")
        else
            local name, icon, _, _ = GetSmithingResearchLineInfo(thisCraft, i)  -- Get info on that specific item
            AIRG.UI.columnButtons[i]:SetNormalTexture(icon)
            AIRG.UI.columnButtons[i]:SetHidden(false)
            AIRG.UI.columnButtons[i].text = name

            traitCount = 0
            --Check for research expiry
            for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
              if (tKnown > 0 and tKnown < GetTimeStamp()) then
                AIRG.vars.data[AIRG.curCharacter][thisCraft][i][rowNum] = -1  -- Change to known
              end
            end


            if  AIRG.ShowRelative
            then
              -- Great! relative mode! we need to address a matter of practical usage.
              --  We need to see that we actually can research that now, because we can't research more than one item type at a time.
              --  So we need to pre-check for item research and set the colours (of the texture) appropriately
              for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
                  if (tKnown > 0) then  -- researching
                      busy = true
                  end
              end

              for rowNum,tKnown in pairs(AIRG.relative[AIRG.curCharacter][thisCraft][i]) do
				  AIRG.UI.gridButtons[i][rowNum].Known = tKnown
                  if (tKnown == -1) then       -- Trait is known
                    if (busy) then
                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.7, 0.6, 0.6, .8)   -- Dull Reddish
                    else
                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
						AIRG.UI.gridButtons[i][rowNum]:SetMouseEnabled(true)
                    end
					tooltiptext = zo_strjoin(" ",AIRG.UI.rowLabels[rowNum]:GetText() , AIRG.UI.columnButtons[i].text)
					AIRG.UI.gridButtons[i][rowNum].tooltipText = tooltiptext
                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("/esoui/art/loot/loot_finesseitem.dds")
                    traitCount = traitCount + 1
                  end
              end


            else -- not relative
              for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
				AIRG.UI.gridButtons[i][rowNum].Known = tKnown

                if (tKnown == -1) then       -- Trait is known
                    AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("/esoui/art/loot/loot_finesseitem.dds")
                    traitCount = traitCount + 1
					tooltiptext = zo_strjoin(" ",AIRG.UI.rowLabels[rowNum]:GetText() , AIRG.UI.columnButtons[i].text)
					AIRG.UI.gridButtons[i][rowNum].tooltipText = tooltiptext
					AIRG.UI.gridButtons[i][rowNum]:SetMouseEnabled(true)
                elseif (tKnown > 0) then   -- Trait is being researched
                        AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/mounts/timer_icon.dds")
                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.5, 0.5, 1, 1)   -- Blue
                        AIRG.UI.gridButtons[i][rowNum]:SetMouseEnabled(true)
                else                        -- Trait is NOT known
                    AIRG.UI.gridButtons[i][rowNum]:SetColor(1, 0.2, 0.2, 1)   -- Red
                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/buttons/decline_up.dds")  --  an   "X".
                end
              end
            end  --Relative

            AIRG.UI.columnFooters[i]:SetText(traitCount)
			alltraits = alltraits + traitCount
        end
    end
	AIRG.UI.columnFooterTitle:SetText(GetString(SI_CRAFTING_COMPONENT_TOOLTIP_TRAITS) .. "(" .. tostring(alltraits) .. ")")   -- "Traits"
end -- AIRG:OnCraftSelected

-- Invoked when the user selected a character from the dropdown box
function AIRG.OnCharacterSelect(charName)

    if (charName == nil) then
        return
    end
    AIRG.curCharacter = charName

      -- The Relative Button doesn't make sense if selecting these
    if charName == AIRG.all or charName == AIRG.playerName then
      AIRG.UI.btnUpdateOther:SetEnabled(false)
      AIRG.ShowRelative = false
    else
      AIRG.UI.btnUpdateOther:SetEnabled(true)
    end

    AIRG.DisplayStyles()
    AIRG.OnCraftSelected()

end -- AIRG.OnCharacterSelect

-- Deletes data for the named character from the saved data and removes them from the dropdown box.
function AIRG.DeleteCharacter(charName)
	local i,item
    -- Can't delete the current character
    if (charName == AIRG.curCharacter) then
        d(AIRG.L["DeleteFalse"])
    else
        if (AIRG.vars.data[charName] ~= nil) then
            AIRG.vars.data[charName] = nil
            d(AIRG.L["DeleteTrue"] .. charName)
        end
        if (AIRG.vars.styles[charName] ~= nil) then
            AIRG.vars.styles[charName] = nil
        end
        AIRG.PopulateAll()
		--this part is new, Thank you Garkin
        for i, item in ipairs(AIRG.UI.charDropdown.dropdown.m_sortedItems) do
            if item.name == charName then
                table.remove(AIRG.UI.charDropdown.dropdown.m_sortedItems, i)
                break
            end
        end
        AIRG.UI.charDropdown.dropdown:UpdateItems()
    end
end -- AIRG.DeleteCharacter

-- This function cycles through all three professions and populates the data matrix for this characters
-- This is carried out when the addon loads to ensure the current character data is up-to-date.
-- The "if" logic in this function guesses at which profession should be default to display as the one with most research in.
function AIRG.PopulateMatrix()
    local curCount = 0
    local thisCount
        AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING  --Default for new chars
        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_BLACKSMITHING)
        if (thisCount > curCount) then
          AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING
          curCount = thisCount
        end
        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_CLOTHIER)
        if (thisCount > curCount) then
          AIRG.curCraft = CRAFTING_TYPE_CLOTHIER
            curCount = thisCount
        end
        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_WOODWORKING)
        if (thisCount > curCount) then
          AIRG.curCraft = CRAFTING_TYPE_WOODWORKING
          curCount = thisCount
        end
      AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_BLACKSMITHING)
      AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_WOODWORKING)
      AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_CLOTHIER)
end -- AIRG.PopulateMatrix

-- Lookup the style data for the current character and send it to saved vars.
function AIRG.PopulateStyleData()
      AIRG.vars.styles[AIRG.curCharacter] = {}    -- create a table for this character's matrix
      local j, known
      for i = 1, 14 do
        j = AIRG.styleLookupItem[i]
        known = IsSmithingStyleKnown(j, 1) --patternIndex set to 1, temporary workaround for changes introduced in Update 4
        AIRG.vars.styles[AIRG.curCharacter][i] = known
      end

      --Dwemer style chapters
      AIRG.vars.styles[AIRG.curCharacter][15] = {}
      local itemStyle = AIRG.styleLookupItem[15]
      for i = 1, 14 do
        --local known = IsSmithingStyleKnown(itemStyle, i)
        local _, numCompleted = GetAchievementCriterion(1144, i)
        AIRG.vars.styles[AIRG.curCharacter][15][AIRG.styleChaptersLookup[i]] = numCompleted == 1
      end

      --Glass style chapters
      AIRG.vars.styles[AIRG.curCharacter][16] = {}
      local itemStyle = AIRG.styleLookupItem[16]
      for i = 1, 14 do
        --local known = IsSmithingStyleKnown(itemStyle, i)
        local _, numCompleted = GetAchievementCriterion(1319, i)
        AIRG.vars.styles[AIRG.curCharacter][16][AIRG.styleChaptersLookup[i]] = numCompleted == 1
      end

      --Xiv Style chapters
      AIRG.vars.styles[AIRG.curCharacter][17] = {}
      local itemStyle = AIRG.styleLookupItem[17]
      for i = 1, 14 do
        local _, numCompleted = GetAchievementCriterion(1181, i)
        AIRG.vars.styles[AIRG.curCharacter][17][AIRG.styleChaptersLookup[i]] = numCompleted == 1
      end

      --Ancient Orc Style chapters
      AIRG.vars.styles[AIRG.curCharacter][18] = {}
      local itemStyle = AIRG.styleLookupItem[18]
      for i = 1, 14 do
        local _, numCompleted = GetAchievementCriterion(1341, i)
        AIRG.vars.styles[AIRG.curCharacter][18][AIRG.styleChaptersLookup[i]] = numCompleted == 1
      end
end -- AIRG.PopulateStyleData

-- When any character data changes we have to go through and create our virtual "All" from the beginning.
-- its simplified by not having to reset to unknown as traits can't be forgotton.
-- The ALL char data was erased at startup
function AIRG.PopulateAll()
    local craft, item, trait, thisname, style, known
    for thisname, _ in pairs(AIRG.vars.data) do   --iterate over all characters
      if thisname ~= AIRG.all then                --skip our virtual
        for craft, _ in pairs(AIRG.vars.data[thisname]) do   --iterate over all crafts
          for item, _ in pairs(AIRG.vars.data[thisname][craft]) do   --iterate over all weapons/armour
            for trait, _ in pairs(AIRG.vars.data[thisname][craft][item]) do   --iterate over all traits
              if AIRG.vars.data[thisname][craft][item][trait] ~=  0 then -- researching counts as learned.
                 AIRG.vars.data[AIRG.all][craft][item][trait] = -1
              end
            end
          end
        end
		-- Fix crash for empty data.
		if AIRG.vars.styles[thisname] == nil then
			AIRG.vars.styles[thisname] = {}
		end
        -- Update the Styles for this char.
		for i = 1, 14 do	--iterate over all non-dwemer styles
			if  AIRG.vars.styles[thisname][i] then
				AIRG.vars.styles[AIRG.all][i] = true
			end
		end
		--Update Dwemer styles
		for i = 1, 14 do	--iterate over all dwemer items
			if  AIRG.vars.styles[thisname][15][i] then
				AIRG.vars.styles[AIRG.all][15][i] = true
			end
		end
		--Update Glass styles
		for i = 1, 14 do	--iterate over all Glass items
			if  AIRG.vars.styles[thisname][16][i] then
				AIRG.vars.styles[AIRG.all][16][i] = true
			end
		end
		--Update Xivkyn styles
		for i = 1, 14 do	--iterate over all Xiv items
			if  AIRG.vars.styles[thisname][17][i] then
				AIRG.vars.styles[AIRG.all][17][i] = true
			end
		end
		--Update Ancient Orc styles
		for i = 1, 14 do	--iterate over all Xiv items
			if  AIRG.vars.styles[thisname][18][i] then
				AIRG.vars.styles[AIRG.all][18][i] = true
			end
		end


      end
    end
end  -- AIRG.PopulateAll


-- Set the icon highlights for the currently selected character
function AIRG.DisplayStyles()
    if (AIRG.vars.styles[AIRG.curCharacter] == nil) then
        for i = 1, 18 do
            AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
            AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
        end
    else
        for i = 1, 18 do
            if (AIRG.vars.styles[AIRG.curCharacter][i]) then
                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "down.dds")
                AIRG.UI.motifButtons[i]:SetColor(0.7, 1, 0.7, 1)   -- Green
            else
                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
                AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
            end
        end
    end
	--Dwemer Motif, special case
	--update old saved variables, if exists

	--making styleIndex as variable, so it will be easier to make a loop if there will be any new styles
	local styleIndex = 15
        -- start of loop if its ever written
	local tooltipText = ""
	local knownCount = 0
	for i = 1, 14 do
		--check how many chapters are known and build tooltip
		if (AIRG.vars.styles[AIRG.curCharacter][styleIndex][i]) then
		   tooltipText = zo_strjoin(nil, tooltipText, "\n|cFFFFFF", GetString("SI_ITEMSTYLECHAPTER", i), "|r")
		   knownCount = knownCount + 1
		else
		   tooltipText = zo_strjoin(nil, tooltipText, "\n|c808080", GetString("SI_ITEMSTYLECHAPTER", i), "|r")
		end
	end
	if knownCount == 0 then
		AIRG.UI.motifButtons[styleIndex]:SetTexture(AIRG.styleLookupIcons[styleIndex] .. "up.dds")
		AIRG.UI.motifButtons[styleIndex]:SetColor(1, 1, 1, 0.7)   -- grey
	else
		AIRG.UI.motifButtons[styleIndex]:SetTexture(AIRG.styleLookupIcons[styleIndex] .. "down.dds")
		if knownCount == 14 then
			AIRG.UI.motifButtons[styleIndex]:SetColor(0.7, 1, 0.7, 1)  -- Green
		else
			AIRG.UI.motifButtons[styleIndex]:SetColor(1, 1, 0.7, 1)    -- yellow
		end
	end
	local itemStyle = AIRG.styleLookupValue[styleIndex]
	local tDesc = GetSmithingStyleItemLink(AIRG.styleLookupItem[styleIndex])
	AIRG.UI.motifButtons[styleIndex].tooltipText = zo_strjoin(nil, zo_strformat("<<t:1>> (<<2>>/14)\n<<t:3>>\n", GetString("SI_ITEMSTYLE", itemStyle), knownCount, tDesc), tooltipText)


	--Glass Motif, special case

	--making styleIndex as variable
	local styleIndex = 16
	--
	local tooltipText = ""
	local knownCount = 0
	for i = 1, 14 do
		-- check how many chapters are known and build tooltip
		if (AIRG.vars.styles[AIRG.curCharacter][styleIndex][i]) then
		   tooltipText = zo_strjoin(nil, tooltipText, "\n|cFFFFFF", GetString("SI_ITEMSTYLECHAPTER", i), "|r")
		   knownCount = knownCount + 1
		else
		   tooltipText = zo_strjoin(nil, tooltipText, "\n|c808080", GetString("SI_ITEMSTYLECHAPTER", i), "|r")
		end
	end
	if knownCount == 0 then
		AIRG.UI.motifButtons[styleIndex]:SetTexture(AIRG.styleLookupIcons[styleIndex] .. "up.dds")
		AIRG.UI.motifButtons[styleIndex]:SetColor(1, 1, 1, 0.7)   -- grey
	else
		AIRG.UI.motifButtons[styleIndex]:SetTexture(AIRG.styleLookupIcons[styleIndex] .. "down.dds")
		if knownCount == 14 then
			AIRG.UI.motifButtons[styleIndex]:SetColor(0.7, 1, 0.7, 1)  -- Green
		else
			AIRG.UI.motifButtons[styleIndex]:SetColor(1, 1, 0.7, 1)    -- yellow
		end
	end
	local itemStyle = AIRG.styleLookupValue[styleIndex]
	local tDesc = GetSmithingStyleItemLink(AIRG.styleLookupItem[styleIndex])
	AIRG.UI.motifButtons[styleIndex].tooltipText = zo_strjoin(nil, zo_strformat("<<t:1>> (<<2>>/14)\n<<t:3>>\n", GetString("SI_ITEMSTYLE", itemStyle), knownCount, tDesc), tooltipText)

	--Xivkyn Motif, special case

	local styleIndex = 17
	--
	local tooltipText = ""
	local knownCount = 0
	for i = 1, 14 do
		-- check how many chapters are known and build tooltip
		if (AIRG.vars.styles[AIRG.curCharacter][styleIndex][i]) then
		   tooltipText = zo_strjoin(nil, tooltipText, "\n|cFFFFFF", GetString("SI_ITEMSTYLECHAPTER", i), "|r")
		   knownCount = knownCount + 1
		else
		   tooltipText = zo_strjoin(nil, tooltipText, "\n|c808080", GetString("SI_ITEMSTYLECHAPTER", i), "|r")
		end
	end
	if knownCount == 0 then
		AIRG.UI.motifButtons[styleIndex]:SetTexture(AIRG.styleLookupIcons[styleIndex] .. "up.dds")
		AIRG.UI.motifButtons[styleIndex]:SetColor(1, 1, 1, 0.7)   -- grey
	else
		AIRG.UI.motifButtons[styleIndex]:SetTexture(AIRG.styleLookupIcons[styleIndex] .. "down.dds")
		if knownCount == 14 then
			AIRG.UI.motifButtons[styleIndex]:SetColor(0.7, 1, 0.7, 1)  -- Green
		else
			AIRG.UI.motifButtons[styleIndex]:SetColor(1, 1, 0.7, 1)    -- yellow
		end
	end
	local itemStyle = AIRG.styleLookupValue[styleIndex]
	local tDesc = GetSmithingStyleItemLink(AIRG.styleLookupItem[styleIndex])
	AIRG.UI.motifButtons[styleIndex].tooltipText = zo_strjoin(nil, zo_strformat("<<t:1>> (<<2>>/14)\n<<t:3>>\n", GetString("SI_ITEMSTYLE", itemStyle), knownCount, tDesc), tooltipText)

	--Ancient Orc Motif, special case

	local styleIndex = 18
	--
	local tooltipText = ""
	local knownCount = 0
	for i = 1, 14 do
		-- check how many chapters are known and build tooltip
		if (AIRG.vars.styles[AIRG.curCharacter][styleIndex][i]) then
		   tooltipText = zo_strjoin(nil, tooltipText, "\n|cFFFFFF", GetString("SI_ITEMSTYLECHAPTER", i), "|r")
		   knownCount = knownCount + 1
		else
		   tooltipText = zo_strjoin(nil, tooltipText, "\n|c808080", GetString("SI_ITEMSTYLECHAPTER", i), "|r")
		end
	end
	if knownCount == 0 then
		AIRG.UI.motifButtons[styleIndex]:SetTexture(AIRG.styleLookupIcons[styleIndex] .. "up.dds")
		AIRG.UI.motifButtons[styleIndex]:SetColor(1, 1, 1, 0.7)   -- grey
	else
		AIRG.UI.motifButtons[styleIndex]:SetTexture(AIRG.styleLookupIcons[styleIndex] .. "down.dds")
		if knownCount == 14 then
			AIRG.UI.motifButtons[styleIndex]:SetColor(0.7, 1, 0.7, 1)  -- Green
		else
			AIRG.UI.motifButtons[styleIndex]:SetColor(1, 1, 0.7, 1)    -- yellow
		end
	end
	local itemStyle = AIRG.styleLookupValue[styleIndex]
	local tDesc = GetSmithingStyleItemLink(AIRG.styleLookupItem[styleIndex])
	AIRG.UI.motifButtons[styleIndex].tooltipText = zo_strjoin(nil, zo_strformat("<<t:1>> (<<2>>/14)\n<<t:3>>\n", GetString("SI_ITEMSTYLE", itemStyle), knownCount, tDesc), tooltipText)





	--end --end of the future loop
end -- AIRG.DisplayStyles()

-- Look up all the data on this profession and commit to saved variables for this character.
function AIRG.CreateDataMatrix(thisCraft)  -- for current  player, not the selected
  local i, j
    local tType, tKnown, tRemain, rowNum, tTargetStamp
    local rCount = 0
    local maxLines = GetNumSmithingResearchLines(thisCraft)     -- the number of columns for this profession
    AIRG.vars.data[AIRG.playerName][thisCraft] = {}             -- create a table for this profession for real traits

    -- Not relative updates, show all for Current Character
    -- Cycle through items for this profession
    for i = 1, maxLines do
        AIRG.vars.data[AIRG.playerName][thisCraft][i] = {}      -- create a table for this item
        -- Cycle through the traits for this item
        for j = 1, 9 do
            tType,_,tKnown = GetSmithingResearchLineTraitInfo(thisCraft,i,j)
            _,tRemain = GetSmithingResearchLineTraitTimes(thisCraft,i,j)
            rowNum = AIRG.gridTraits[tType]

            if (tKnown) then
                AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = -1       -- this trait is known
                rCount = rCount + 1
            else
                if (tRemain) then
                    tTargetStamp = GetTimeStamp() + tRemain
                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = tTargetStamp   -- this trait is being currently researched
                    -- The value we are setting this to is the timestamp for when the research will be complete.
                else
                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = 0   -- this trait is NOT known
                end
            end
        end

    end
    return rCount       -- the total number of traits already researched in this profession
end -- AIRG.CreateDataMatrix

function AIRG.CreateDataMatrixRelative(thisCraft)  -- for the current selected  player, relative to the real player
    local craft, item, trait, thisname, style, known

    for thisname, _ in pairs(AIRG.vars.data) do   --iterate over all characters
      if thisname ~= AIRG.all then                --skip our virtual
        AIRG.relative[thisname] = {}
        for craft, _ in pairs(AIRG.vars.data[thisname]) do   --iterate over all crafts
          AIRG.relative[thisname][craft] = {}
          for item, _ in pairs(AIRG.vars.data[thisname][craft]) do   --iterate over all weapons/armour
            AIRG.relative[thisname][craft][item] = {}
            for trait, _ in pairs(AIRG.vars.data[thisname][craft][item]) do   --iterate over all traits
              AIRG.relative[thisname][craft][item][trait] = {}
              if AIRG.vars.data[thisname][craft][item][trait] ==  0 then -- thischar doesn't have traits
                if AIRG.vars.data[AIRG.playerName][craft][item][trait] ==  -1  ---PLayer Does
                then AIRG.relative[thisname][craft][item][trait] = -1
                else AIRG.relative[thisname][craft][item][trait] = nil
                end
              end
            end
          end
        end
      end
    end
end -- AIRG.CreateDataMatrix



function AIRG.AssignGridTraits()
    -- Translates the traitType to the correct ROW of the grid
    AIRG.gridTraits = {}
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_POWERED] = 1
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_CHARGED] = 2
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_PRECISE] = 3
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_INFUSED] = 4
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_DEFENDING] = 5
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_TRAINING] = 6
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_SHARPENED] = 7
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_WEIGHTED] = 8
    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_NIRNHONED] = 9
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_STURDY] = 10
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_IMPENETRABLE] = 11
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_REINFORCED] = 12
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_WELL_FITTED] = 13
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_TRAINING] = 14
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_INFUSED] = 15
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_EXPLORATION] = 16
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_DIVINES] = 17
    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_NIRNHONED] = 18
end -- AIRG.AssignGridTraits

function AIRG.AssignStyleLookups()
    -- Lookup the correct icon for the style
    AIRG.styleLookupIcons = {}
    AIRG.styleLookupIcons[1] = "ESOUI/art/charactercreate/charactercreate_altmericon_"
    AIRG.styleLookupIcons[2] = "ESOUI/art/charactercreate/charactercreate_dunmericon_"
    AIRG.styleLookupIcons[3] = "ESOUI/art/charactercreate/charactercreate_bosmericon_"
    AIRG.styleLookupIcons[4] = "ESOUI/art/charactercreate/charactercreate_nordicon_"
    AIRG.styleLookupIcons[5] = "ESOUI/art/charactercreate/charactercreate_bretonicon_"
    AIRG.styleLookupIcons[6] = "ESOUI/art/charactercreate/charactercreate_redguardicon_"
    AIRG.styleLookupIcons[7] = "ESOUI/art/charactercreate/charactercreate_khajiiticon_"
    AIRG.styleLookupIcons[8] = "ESOUI/art/charactercreate/charactercreate_orcicon_"
    AIRG.styleLookupIcons[9] = "ESOUI/art/charactercreate/charactercreate_argonianicon_"
    AIRG.styleLookupIcons[10] = "ESOUI/art/charactercreate/charactercreate_imperialicon_"
    AIRG.styleLookupIcons[11] = "ESOUI/art/progression/progression_indexicon_weapons_"
    AIRG.styleLookupIcons[12] = "ESOUI/art/progression/progression_indexicon_weapons_"
    AIRG.styleLookupIcons[13] = "ESOUI/art/progression/progression_indexicon_weapons_"
    AIRG.styleLookupIcons[14] = "ESOUI/art/progression/progression_indexicon_weapons_"
    AIRG.styleLookupIcons[15] = "ESOUI/art/progression/progression_indexicon_weapons_"
    AIRG.styleLookupIcons[16] = "ESOUI/art/progression/progression_indexicon_weapons_"
    AIRG.styleLookupIcons[17] = "ESOUI/art/progression/progression_indexicon_weapons_"
    AIRG.styleLookupIcons[18] = "ESOUI/art/progression/progression_indexicon_weapons_"


    -- Translate the icon position to the in-game type. Used for text look-up
    AIRG.styleLookupValue = {}
    AIRG.styleLookupValue[1] = ITEMSTYLE_RACIAL_HIGH_ELF
    AIRG.styleLookupValue[2] = ITEMSTYLE_RACIAL_DARK_ELF
    AIRG.styleLookupValue[3] = ITEMSTYLE_RACIAL_WOOD_ELF
    AIRG.styleLookupValue[4] = ITEMSTYLE_RACIAL_NORD
    AIRG.styleLookupValue[5] = ITEMSTYLE_RACIAL_BRETON
    AIRG.styleLookupValue[6] = ITEMSTYLE_RACIAL_REDGUARD
    AIRG.styleLookupValue[7] = ITEMSTYLE_RACIAL_KHAJIIT
    AIRG.styleLookupValue[8] = ITEMSTYLE_RACIAL_ORC
    AIRG.styleLookupValue[9] = ITEMSTYLE_RACIAL_ARGONIAN
    AIRG.styleLookupValue[10] = ITEMSTYLE_AREA_IMPERIAL
    AIRG.styleLookupValue[11] = ITEMSTYLE_AREA_ANCIENT_ELF
    AIRG.styleLookupValue[12] = ITEMSTYLE_AREA_REACH
    AIRG.styleLookupValue[13] = ITEMSTYLE_ENEMY_DAEDRIC
    AIRG.styleLookupValue[14] = ITEMSTYLE_ENEMY_PRIMITIVE
    AIRG.styleLookupValue[15] = ITEMSTYLE_AREA_DWEMER
    AIRG.styleLookupValue[16] = ITEMSTYLE_GLASS
    AIRG.styleLookupValue[17] = ITEMSTYLE_AREA_XIVKYN
    AIRG.styleLookupValue[18] = ITEMSTYLE_AREA_ANCIENT_ORC

    -- This is a bit of a hack, but only because of the way ESO uses Style Items with different index to styles.
    AIRG.styleLookupItem = {}
    AIRG.styleLookupItem[1] = 8     -- Altmer       = Adamantite
    AIRG.styleLookupItem[2] = 5     -- Dunmer       = Obsidian
    AIRG.styleLookupItem[3] = 9     -- Bosmer       = Bone
    AIRG.styleLookupItem[4] = 6     -- Nord         = Corundum
    AIRG.styleLookupItem[5] = 2     -- Breton       = Molybdenum
    AIRG.styleLookupItem[6] = 3     -- Redguard     = Starmetal
    AIRG.styleLookupItem[7] = 10    -- Khajit       = Moonstone
    AIRG.styleLookupItem[8] = 4     -- Orc          = Manganese
    AIRG.styleLookupItem[9] = 7     -- Argonian     = Flint
    AIRG.styleLookupItem[10] = 35   -- Imperial     = Nickel
    AIRG.styleLookupItem[11] = 16   -- Ancient Elf  = Palladium
    AIRG.styleLookupItem[12] = 18   -- Barbarian    = Copper
    AIRG.styleLookupItem[13] = 21   -- Daedric      = Daedra Heart
    AIRG.styleLookupItem[14] = 20   -- Primal       = Argentum
    AIRG.styleLookupItem[15] = 15   -- Dwemer       = Dwemer Frame
    AIRG.styleLookupItem[16] = 29   -- Glass        = Malachite Shard
    AIRG.styleLookupItem[17] = 30   -- Xivkyn       = ??
    AIRG.styleLookupItem[18] = 23   -- Ancient Orc  = ??

    AIRG.styleChaptersLookup = {}
    AIRG.styleChaptersLookup[1] = 10   --Axe
    AIRG.styleChaptersLookup[2] = 6    --Belt
    AIRG.styleChaptersLookup[3] = 3    --Boots
    AIRG.styleChaptersLookup[4] = 14   --Bows
    AIRG.styleChaptersLookup[5] = 5    --Chests
    AIRG.styleChaptersLookup[6] = 11   --Daggers
    AIRG.styleChaptersLookup[7] = 2    --Gloves
    AIRG.styleChaptersLookup[8] = 1    --Helmets
    AIRG.styleChaptersLookup[9] = 4    --Legs
    AIRG.styleChaptersLookup[10] = 9   --Maces
    AIRG.styleChaptersLookup[11] = 13  --Shields
    AIRG.styleChaptersLookup[12] = 7   --Shoulders
    AIRG.styleChaptersLookup[13] = 12  --Staves
    AIRG.styleChaptersLookup[14] = 8   --Swords

end -- AIRG.AssignStyleLookups


function AIRG.Initialise(eventCode, addOnName)
	-- Only initialize our own addon
	if (AIRG.name ~= addOnName) then return end
    -- Language text
    AIRG.InitialiseLanguage()

    -- Load the saved variables
    AIRG.vars = ZO_SavedVars:NewAccountWide("AIRG_SavedVariables", 2, nil, AIRG.defaults)
    AIRG.all = AIRG.L["ALL"]		-- replace Default with localise string

    -- Register Keybinding
    ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_AIRG", "Toggle AI Research Grid")

	-- Set-up some variables we'll want to refer to.
    AIRG.craftNames = {}
    AIRG.relative = {}
    AIRG.craftNames[CRAFTING_TYPE_BLACKSMITHING]    = AIRG.L["BS"]
    AIRG.craftNames[CRAFTING_TYPE_CLOTHIER]         = AIRG.L["Clothing"]
    AIRG.craftNames[CRAFTING_TYPE_WOODWORKING]      = AIRG.L["Woodwork"]
    AIRG.curCraft= CRAFTING_TYPE_WOODWORKING
    AIRG.playerName = GetUnitName("player")
    AIRG.curCharacter = GetUnitName("player")       -- Default the display to the current character
    AIRG.AssignGridTraits()
    AIRG.AssignStyleLookups()

	--Remove possibly spurious character data
	AIRG.vars.styles["#TOUS"] = nil
	AIRG.vars.styles[" #ALLE"] = nil
	AIRG.vars.styles[" #ALL"] = nil

	AIRG.vars.styles[AIRG.all] = {}
    -- Create these here so the UI dropdown will have them first time around.
    AIRG.vars.data[AIRG.playerName] = {}    -- create a table for this character's matrix

	--Remove possibly spurious character data
	AIRG.vars.data["#TOUS"] = nil
	AIRG.vars.data[" #ALLE"] = nil
	AIRG.vars.data[" #ALL"] = nil
    AIRG.vars.data[AIRG.all] = {}    -- and our virtual character
  -- Create Empty data for Virtual Char set to 0, (Not known)
    local i, j

    AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING] = {}
    -- Cycle through items for this profession
    for i = 1, 7 do   -- Weapons
        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i] = {}
        -- Cycle through the traits for this item
        for j = 1, 9 do
                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i][j] = 0   -- set to not known
        end
    end
    for i = 8, 14 do  -- Armour
        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i] = {}
        -- Cycle through the traits for this item
        for j = 10, 18 do
                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i][j] = 0   -- set to not known
        end
    end

    AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER] = {}
    -- Cycle through items for this profession
    for i = 1, 14 do
        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER][i] = {}
        -- Cycle through the traits for this item
        for j = 10, 18  do
                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER][i][j] = 0   -- set to not known
        end
    end

     AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING] = {}
    -- Cycle through items for this profession
    for i = 1, 5 do
        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i] = {}
        -- Cycle through the traits for this item
        for j = 1, 9 do
                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i][j] = 0   -- set to not known
        end
    end
    for i = 6, 6 do  --Shields
        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i] = {}
        -- Cycle through the traits for this item
        for j = 10, 18 do
                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i][j] = 0   -- set to not known
        end
    end

    --Create Empty Style Table
    for i = 1, 14 do
        AIRG.vars.styles[AIRG.all][i] = false
    end

	AIRG.vars.styles[AIRG.all][15]= {}	--Dwemer
    for i = 1, 14 do
        AIRG.vars.styles[AIRG.all][15][i] = false
    end
	AIRG.vars.styles[AIRG.all][16]= {}	--Glass
    for i = 1, 14 do
        AIRG.vars.styles[AIRG.all][16][i] = false
    end
	AIRG.vars.styles[AIRG.all][17]= {}	--Xiv
    for i = 1, 14 do
        AIRG.vars.styles[AIRG.all][17][i] = false
    end

	AIRG.vars.styles[AIRG.all][18]= {}	--Ancient Orc
    for i = 1, 14 do
        AIRG.vars.styles[AIRG.all][18][i] = false
    end


 -- AIRG.CreateDataMatrix

    -- Following replaced with PlayerActivate
    -- Query data for THIS character and populate the data matrix with fresh data.
    --AIRG.PopulateMatrix()

    -- Query data for THIS character for STYLES
    --AIRG.PopulateStyleData()

    -- UI set-up. Create frames, position labels & buttons etc.
    AIRG.initUI()
	-- Create the configuration/settings menu.
    AIRG.CreateConfigMenu()
    -- REGISTER for events that aren't initialise.
    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_STARTED, AIRG.ResearchStarted)
    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED, AIRG.ResearchCompleted)

    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_STYLE_LEARNED, AIRG.StyleLearned)

    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_PLAYER_ACTIVATED, AIRG.PlayerActivated)
	SCENE_MANAGER:RegisterTopLevel(AIResearchGrid, false)		-- enables close on Esc
    AIRG.initialised = true
end -- AIRG.Initialise

-- SLASH COMMAND FUNCTIONALITY
function AIRGslash(extra)
    AIRG.ToggleMainWindow()
end -- AIRGslash

SLASH_COMMANDS["/airg"] = AIRGslash
EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_ADD_ON_LOADED, AIRG.Initialise)
-- EOF