local AtlasLoot = _G.AtlasLoot
local GUI = AtlasLoot.GUI
local ItemDB = AtlasLoot.ItemDB
local ItemFrame = {}
AtlasLoot.GUI.ItemFrame = ItemFrame
local AL = AtlasLoot.Locales
local ClassFilter = AtlasLoot.Data.ClassFilter

-- lua
local type, tostring = type, tostring
local floor = math.floor
local format, sfind, slower = string.format, string.find, string.lower

-- WoW
local GetTime = GetTime
local Transmog = AtlasLoot.Transmog:New()

local LastRefresh = GetTime()
local PAGE_NAME_PAGE = "%s [%d/%d]"
local PAGE_NAME_DIFF = "%s (%s)"
local PAGE_NAME_DIFF_PAGE = "%s (%s) [%d/%d]"
local FILTER_ALPHA = 0.33
local DEFAULT_HEADER_COLOR = {0.82, 0.82, 0.82, 0.5}

function ItemFrame:Create()
    if self.frame then return self.frame end
    local frameName = "AtlasLoot_GUI-ItemFrame"

    self.frame = CreateFrame("FRAME", frameName, GUI.frame)
    local frame = self.frame
    frame:ClearAllPoints()
    frame:SetParent(GUI.frame)
    frame:SetPoint("TOPLEFT", GUI.frame.contentFrame.itemBG)
    frame:SetWidth(560)
    frame:SetHeight(450)
    --frame:Hide()
    -- create all item buttons
    frame.Refresh = ItemFrame.Refresh
    frame.Clear = ItemFrame.Clear
    frame.OnSearch = ItemFrame.OnSearch
    frame.OnSearchClear = ItemFrame.OnSearchClear
    frame.OnSearchTextChanged = ItemFrame.OnSearchTextChanged
    frame.OnClassFilterUpdate = ItemFrame.OnClassFilterUpdate
    frame.OnTransMogUpdate = ItemFrame.OnTransMogUpdate

    frame.ItemButtons = {}
    for i=1,30 do
        frame.ItemButtons[i] = AtlasLoot.Button:Create()
        frame.ItemButtons[i]:ClearAllPoints()
        frame.ItemButtons[i]:SetParent(frame)
        if i == 1 then
            frame.ItemButtons[i]:SetPoint("TOPLEFT", frame, "TOPLEFT", 5)
        elseif i == 16 then
            frame.ItemButtons[i]:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, 0)
        else
            frame.ItemButtons[i]:SetPoint("TOPLEFT", frame.ItemButtons[i-1], "BOTTOMLEFT", 0, -2)
        end
    end
    -- headerlines
    frame.HeaderLines = {}
    for i = 1, 15 do
        local line
        line = frame:CreateTexture(nil, "BACKGROUND")
        line:SetPoint("TOPLEFT", frame.ItemButtons[i], "TOPLEFT", 0, 0)
        line:SetPoint("BOTTOMRIGHT", frame.ItemButtons[i+15], "BOTTOMRIGHT", 0, 0)
        line:SetColorTexture(unpack(DEFAULT_HEADER_COLOR))
        line:SetDrawLayer(GUI.frame.contentFrame.itemBG:GetDrawLayer(), 1)
        --GUI.frame.contentFrame.itemBG
        line:Hide()
        frame.HeaderLines[i] = line
    end

    return self.frame
end

function ItemFrame:Show(noRefresh)
    if not ItemFrame.frame:IsShown() or GUI.frame.contentFrame.shownFrame ~= ItemFrame.frame then
        GUI:HideContentFrame()
        ItemFrame.frame:Show()
        GUI.frame.contentFrame.shownFrame = ItemFrame.frame
        if not noRefresh then
            ItemFrame:Refresh()
        end
    end
end

function ItemFrame:ClearItems()
    for i=1,30 do
        self.frame.ItemButtons[i]:Clear()
        self.frame.ItemButtons[i]:Hide()
    end
end

function ItemFrame.UpdateFilterItem(buttonID, reset)
    local button = ItemFrame.frame.ItemButtons[buttonID] or buttonID
    if not button then return end
    if AtlasLoot.db.GUI.classFilter then
        if button and button.__atlaslootinfo and not button.__atlaslootinfo.filterIgnore and button.__atlaslootinfo.type and (button.__atlaslootinfo.type[1] == "Item" or button.filterItemID) then
            if (button.filterItemID or button.ItemID) and ClassFilter.ClassCanUseItem(GUI.frame.contentFrame.clasFilterButton.selectedClassName, button.filterItemID or button.ItemID) then
                button:SetAlpha(1)
            else
                button:SetAlpha(0.33)
            end
        else
            button:SetAlpha(1)
        end
        reset = false
    end

    if ItemFrame.SearchString then
        local text = button.RawName or button.name:GetText()
        if text and not sfind(slower(text), ItemFrame.SearchString, 1, true) then
            button:SetAlpha(FILTER_ALPHA)
        elseif reset then
            button:SetAlpha(1.0)
        end
        reset = false
    end

    return reset
end

function ItemFrame.UpdateFilter()
    local reset = true
    for i = 1,30 do
        reset = ItemFrame.UpdateFilterItem(i, reset)
    end

    if reset then
        for i=1,30 do
            ItemFrame.frame.ItemButtons[i]:SetAlpha(1)
        end
    end
end

function ItemFrame.OnClassFilterUpdate()
    ItemFrame.UpdateFilter()
end

local function TransmogCallback(button, collected)
    if collected == nil then
        button.highlightBg:Hide()
    elseif collected == false then
        button.highlightBg:SetColorTexture(1,0,0)
        button.highlightBg:Show()
    elseif collected == true then
        button.highlightBg:SetColorTexture(0,1,0)
        button.highlightBg:Show()
    end
end

function ItemFrame.OnTransMogUpdate()
    if AtlasLoot.db.GUI.transmogHighlighter then
        Transmog:Clear()
        local button
        for i = 1,30 do
            button = ItemFrame.frame.ItemButtons[i]
            if button.ItemString or button.ItemID then
                Transmog:IsItemUnlocked(button.ItemString or button.ItemID, nil, TransmogCallback, button)
            else
                button.highlightBg:Hide()
            end
        end
    else
        for i = 1,30 do
            ItemFrame.frame.ItemButtons[i].highlightBg:Hide()
        end
    end
end

function ItemFrame.OnSearch(msg)
    ItemFrame.SearchString = ( not msg or msg == "" ) and nil or slower(msg)
    ItemFrame.UpdateFilter()
end

function ItemFrame.OnSearchClear()
    ItemFrame.SearchString = nil
    ItemFrame.UpdateFilter()
end

function ItemFrame.OnSearchTextChanged(msg)
    ItemFrame.SearchString = ( not msg or msg == "" ) and nil or slower(msg)
    ItemFrame.UpdateFilter()
end

function ItemFrame:Refresh(skipProtect)
    -- small spam protection
    if not skipProtect and GetTime() - LastRefresh < 0.1 then return end
    LastRefresh = GetTime()

    ItemFrame:ClearItems()
    AtlasLoot.db.GUI.selected[5] = AtlasLoot.db.GUI.selected[5] or 0
    ItemFrame.nextPage = nil
    local page = AtlasLoot.db.GUI.selected[5] * 100 -- Page number for first items on a page are <1, 101, 201, 301, 401, ...>
    local bossData = AtlasLoot.ItemDB:GetBossTable(AtlasLoot.db.GUI.selected[1], AtlasLoot.db.GUI.selected[2], AtlasLoot.db.GUI.selected[3])
    local items, tableType, diffData = ItemDB:GetItemTable(AtlasLoot.db.GUI.selected[1], AtlasLoot.db.GUI.selected[2], AtlasLoot.db.GUI.selected[3], AtlasLoot.db.GUI.selected[4])
    if items then

        ItemFrame.LinkedInfo = items.__linkedInfo
        ItemFrame.CurDiff = diffData.difficultyID or 1
        ItemFrame.CurTier = diffData.tierID or 1
        -- refresh title with diff and add pagenumber if there
            if #items and items[#items] and items[#items][1] > 100 then
                if not diffData.textIsHidden then
                    GUI.frame.contentFrame.title:SetText(format(PAGE_NAME_DIFF_PAGE, GUI.frame.contentFrame.title.txt, diffData.name, AtlasLoot.db.GUI.selected[5]+1, floor(items[#items][1]/100)+1))
                else
                    GUI.frame.contentFrame.title:SetText(format(PAGE_NAME_PAGE, GUI.frame.contentFrame.title.txt, AtlasLoot.db.GUI.selected[5]+1, floor(items[#items][1]/100)+1))
                end
            else
                if not diffData.textIsHidden then
                    GUI.frame.contentFrame.title:SetText(format(PAGE_NAME_DIFF, GUI.frame.contentFrame.title.txt or "", diffData.name or ""))
                else
                    GUI.frame.contentFrame.title:SetText(GUI.frame.contentFrame.title.txt or "")
                end
            end
        if type(items) == "string" then
            GUI:ShowLoadingInfo(items, true, tableType)
            AtlasLoot.Loader:LoadModule(items, function() ItemFrame:Refresh(true) GUI.frame.contentFrame.loadingDataText:Hide() end, true)
            return
        end

        local fixItemNum = 0
        local setn,item = nil
        for i = 1,#items do
            item = items[i]
            fixItemNum = item[1] - page
            if ItemFrame.frame.ItemButtons[fixItemNum] then
                ItemFrame.frame.ItemButtons[fixItemNum]:SetDifficultyID(diffData.difficultyID)
                ItemFrame.frame.ItemButtons[fixItemNum]:SetNpcID(ItemFrame.npcID)
                ItemFrame.frame.ItemButtons[fixItemNum]:SetPreSet(diffData.preset)
                ItemFrame.frame.ItemButtons[fixItemNum]:SetContentTable(item, tableType)
                setn = true
            elseif fixItemNum > 100 then
                GUI.frame.contentFrame.nextPageButton.info = tostring(AtlasLoot.db.GUI.selected[5] + 1)
                --break
            end
        end
        -- page not found set it to first page and reset
        if not setn and AtlasLoot.db.GUI.selected[5] ~= 0 then
            AtlasLoot.db.GUI.selected[5] = 0
            ItemFrame:Refresh(true)
            return
        end
    end
    -- calc prev page
    if AtlasLoot.db.GUI.selected[5] - 1 >= 0 then
        GUI.frame.contentFrame.prevPageButton.info = tostring(AtlasLoot.db.GUI.selected[5] - 1)
    else
        --[[	this must be fixed later ... Check for pages
        if AtlasLoot.db.GUI.selected[3] - 1 > 0 then
            items, tableType = ItemDB:GetItemTable(AtlasLoot.db.GUI.selected[1], AtlasLoot.db.GUI.selected[2], AtlasLoot.db.GUI.selected[3]-1, AtlasLoot.db.GUI.selected[4])
            if items and #items > 0 and floor(items[#items][1]/100) > 0 then
                GUI.frame.contentFrame.prevPageButton.info = { AtlasLoot.db.GUI.selected[3]-1, floor(items[#items][1]/100) }
            end
        end
        ]]--
    end
    -- check for headers
    if ItemFrame.headerShown then
        for i = 1, #ItemFrame.frame.HeaderLines do
            ItemFrame.frame.HeaderLines[i]:Hide()
        end
    end
    local headerLines = items.headerLines or bossData.headerLines
    if headerLines then
        local line
        for i = 1, #headerLines do
            line = ItemFrame.frame.HeaderLines[headerLines[i]]
            if line then
                line:SetColorTexture(unpack(headerLines.color or DEFAULT_HEADER_COLOR))
                line:Show()
            end
        end
        ItemFrame.headerShown = true
    end

    ItemFrame.UpdateFilter()
    ItemFrame.OnTransMogUpdate()
end

function ItemFrame.Clear()
    ItemFrame:ClearItems()
    ItemFrame.frame:Hide()
    GUI.frame.contentFrame.shownFrame = nil
end
