local addonName = "Altoholic"
local addon = _G[addonName]

addon:Controller("AltoholicUI.TabCharacters.Auctions", { "AltoholicUI.Options", function(Options)

	local L = LibStub("AceLocale-3.0"):GetLocale(addonName)
	local colors = addon.Colors
	local currentCharacter
	local view, isViewValid
	local viewSortField, viewSortOrder
	local listType		-- "Auctions" or "Bids"
	
	local OPTION_VIEW_AUCTION_HOUSE = "UI.Tabs.Characters.ViewAuctionHouse"

	local function SortByName(a, b, ascending)
		local idA = select(2, DataStore:GetAuctionHouseItemInfo(currentCharacter, listType, a))
		local idB = select(2, DataStore:GetAuctionHouseItemInfo(currentCharacter, listType, b))
		
		local textA = GetItemInfo(idA) or ""
		local textB = GetItemInfo(idB) or ""
		
		if ascending then
			return textA < textB
		else
			return textA > textB
		end
	end

	local function SortByPlayer(a, b, ascending)
		local valueA = select(4, DataStore:GetAuctionHouseItemInfo(currentCharacter, listType, a)) or ""
		local valueB = select(4, DataStore:GetAuctionHouseItemInfo(currentCharacter, listType, b)) or ""
		
		if ascending then
			return valueA < valueB
		else
			return valueA > valueB
		end
	end

	local function SortByPrice(a, b, ascending)
		local valueA = select(6, DataStore:GetAuctionHouseItemInfo(currentCharacter, listType, a))
		local valueB = select(6, DataStore:GetAuctionHouseItemInfo(currentCharacter, listType, b))
	
		if ascending then
			return valueA < valueB
		else
			return valueA > valueB
		end
	end

	local function BuildView(field, ascending)
		field = field or "expiry"
		
		view = view or {}
		wipe(view)
		
		listType = Options.Get(OPTION_VIEW_AUCTION_HOUSE)
		
		local num
		if listType == "Auctions" then
			num = DataStore:GetNumAuctions(currentCharacter) or 0
		else
			num = DataStore:GetNumBids(currentCharacter) or 0
		end
		
		for i = 1, num do
			table.insert(view, i)
		end
		
		if field == "name" then
			table.sort(view, function(a, b) return SortByName(a, b, ascending) end)
		elseif field == "owner" then
			table.sort(view, function(a, b) return SortByPlayer(a, b, ascending) end)
		elseif field == "highBidder" then
			table.sort(view, function(a, b) return SortByPlayer(a, b, ascending) end)
		elseif field == "buyoutPrice" then
			table.sort(view, function(a, b) return SortByPrice(a, b, ascending) end)
		end
		
		isViewValid = true
	end

	return {
		OnBind = function(frame)
			local parent = AltoholicFrame.TabCharacters
			
			frame:SetParent(parent)
			frame:SetPoint("TOPLEFT", parent.Background, "TOPLEFT", 0, 0)
			frame:SetPoint("BOTTOMRIGHT", parent.Background, "BOTTOMRIGHT", 26, 0)
			parent:RegisterPanel("Auctions", frame)
			
			addon:RegisterMessage("DATASTORE_AUCTIONS_UPDATED", function() 

				frame:InvalidateView()
				if frame:IsVisible() then
					frame:Update()
				end
			end)
			
			-- Handle resize
			frame:SetScript("OnSizeChanged", function(self, width, height)
				if not frame:IsVisible() then return end
			
				frame:PreUpdate()
				frame:Update(true)
			end)
		end,
		
		PreUpdate = function(frame)
			-- There is no Update(), it points to UpdateAuctions or UpdateBids
			if Options.Get(OPTION_VIEW_AUCTION_HOUSE) == "Auctions" then
				frame.Update = frame.UpdateAuctions
			else
				frame.Update = frame.UpdateBids
			end
		end,
		Sort = function(frame, field, sortOrder)
			viewSortField = field
			viewSortOrder = sortOrder
			
			frame:InvalidateView()
		end,
		InvalidateView = function()
			isViewValid = nil
		end,
		
		UpdateAuctions = function(frame, isResizing)
			local parent = frame:GetParent()
			local character = parent:GetCharacter()
			if not character then return end
			
			currentCharacter = character
			
			if not isViewValid then
				BuildView(viewSortField, viewSortOrder)
			end
			
			local numAuctions = DataStore:GetNumAuctions(character) or 0
		
			-- Set the tab status
			parent:SetStatus(format("%s|r / %s%s", DataStore:GetColoredCharacterName(character), 
				colors.white, format("%s %s(%d)", AUCTIONS, colors.green, numAuctions)))
			
			-- Update the scrollframe
			local scrollFrame = frame.ScrollFrame
			local numRows = scrollFrame.numRows
			local offset = scrollFrame:GetOffset()
			
			local maxDisplayedRows = math.floor(scrollFrame:GetHeight() / scrollFrame.rowHeight)
			
			for rowIndex = 1, numRows do
				local rowFrame = scrollFrame:GetRow(rowIndex)
				local line = rowIndex + offset
				
				if line <= numAuctions and (rowIndex <= maxDisplayedRows)then	-- if the line is visible
					if not (isResizing and rowFrame:IsVisible()) then
						local index = view[line]
						
						local isGoblin, itemID, count, highBidder, startPrice, buyoutPrice, timeLeft = DataStore:GetAuctionHouseItemInfo(character, "Auctions", index)
						
						if itemID then
							local itemName, _, itemRarity = GetItemInfo(itemID)
							rowFrame:SetName(itemName or L["N/A"], itemRarity or 1)
							rowFrame.Item:SetID(index)
						end
						
						rowFrame:SetTimeLeft(timeLeft)
						rowFrame:SetHighBidder(isGoblin, highBidder)
						rowFrame:SetPrice(startPrice, buyoutPrice)
						rowFrame.Item:SetIcon(GetItemIcon(itemID))
						rowFrame.Item:SetCount(count)
						rowFrame.Item.listType = listType
					end
					rowFrame:Show()
				else
					rowFrame:Hide()
				end
			end

			scrollFrame:Update(#view, maxDisplayedRows)
			frame:Show()
		end,
		UpdateBids = function(frame, isResizing)
			local parent = frame:GetParent()
			local character = parent:GetCharacter()
			if not character then return end
			
			currentCharacter = character
			
			if not isViewValid then
				BuildView(viewSortField, viewSortOrder)
			end
			
			local numBids = DataStore:GetNumBids(character) or 0
		
			-- Set the tab status
			parent:SetStatus(format("%s|r / %s%s", DataStore:GetColoredCharacterName(character), 
				colors.white, format("%s %s(%d)", BIDS, colors.green, numBids)))
			
			-- Update the scrollframe
			local scrollFrame = frame.ScrollFrame
			local numRows = scrollFrame.numRows
			local offset = scrollFrame:GetOffset()
			
			local maxDisplayedRows = math.floor(scrollFrame:GetHeight() / scrollFrame.rowHeight)
			
			for rowIndex = 1, numRows do
				local rowFrame = scrollFrame:GetRow(rowIndex)
				local line = rowIndex + offset
				
				if line <= numBids and (rowIndex <= maxDisplayedRows)then	-- if the line is visible
					if not (isResizing and rowFrame:IsVisible()) then
						local index = view[line]
						
						local isGoblin, itemID, count, ownerName, bidPrice, buyoutPrice, timeLeft = DataStore:GetAuctionHouseItemInfo(character, "Bids", index)
						
						if itemID then
							local itemName, _, itemRarity = GetItemInfo(itemID)
							rowFrame:SetName(itemName or L["N/A"], itemRarity or 1)
							rowFrame.Item:SetID(index)
						end
						
						rowFrame:SetTimeLeftForBid(timeLeft)
						rowFrame:SetOwnBid(isGoblin, ownerName)
						rowFrame:SetBidPrice(bidPrice, buyoutPrice)
						rowFrame.Item:SetIcon(GetItemIcon(itemID))
						rowFrame.Item:SetCount(count)
						rowFrame.Item.listType = listType
					end
					rowFrame:Show()
				else
					rowFrame:Hide()
				end
			end

			scrollFrame:Update(#view, maxDisplayedRows)
			frame:Show()
		end,
	}
end})