-- ------------------------------------------------------------------------------ --
--                                TradeSkillMaster                                --
--                http://www.curse.com/addons/wow/tradeskill-master               --
--                                                                                --
--             A TradeSkillMaster Addon (http://tradeskillmaster.com)             --
--    All Rights Reserved* - Detailed license information included with addon.    --
-- ------------------------------------------------------------------------------ --

local _, TSM = ...
local CustomSources = TSM.MainUI.Settings:NewPackage("CustomSources")
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster") -- loads the localization table
local private = { selectedRow = nil, isEditing = nil }
local NAME_COL_WIDTH = 300



-- ============================================================================
-- Module Functions
-- ============================================================================

function CustomSources.OnInitialize()
	TSM.MainUI.Settings.RegisterSettingPage("Custom Sources", "middle", private.GetCustomSourcesSettingsFrame)
end



-- ============================================================================
-- Custom Sources Settings UI
-- ============================================================================

function private.GetCustomSourcesSettingsFrame()
	return TSMAPI_FOUR.UI.NewElement("ScrollFrame", "content")
		:SetStyle("padding", 10)
		:AddChild(TSMAPI_FOUR.UI.NewElement("Text", "headerText")
			:SetStyle("height", 60)
			:SetStyle("textColor", "#e2e2e2")
			:SetStyle("fontHeight", 16)
			:SetText(L["Price Variables allow you to create more advanced custom prices throughout the entire TSM addon. You’ll be able to use these new variables in the same way you can use the built-in price sources (such as ‘vendorsell’ and ‘vendorbuy’)."])
		)
		:AddChild(TSMAPI_FOUR.UI.NewElement("Button", "newBtn")
			:SetStyle("borderTexture", "Interface\\Addons\\TradeSkillMaster\\Media\\ButtonEdgeFrame.blp")
			:SetStyle("borderSize", 7)
			:SetStyle("margin", 10)
			:SetStyle("height", 20)
			:SetText(L["Add New Custom Price Source"])
			:SetScript("OnClick", private.AddNewButtonOnClick)
		)
		:AddChild(TSMAPI_FOUR.UI.NewElement("Frame", "headerRow")
			:SetLayout("HORIZONTAL")
			:SetStyle("margin", { left = -10, right = -10 })
			:SetStyle("padding", { left = 10, right = 10 })
			:SetStyle("background", "#585858")
			:SetStyle("height", 32)
			:AddChild(TSMAPI_FOUR.UI.NewElement("Text", "nameColText")
				:SetStyle("width", NAME_COL_WIDTH)
				:SetStyle("font", TSM.UI.Fonts.bold)
				:SetStyle("fontHeight", 18)
				:SetStyle("textColor", "#e2e2e2")
				:SetText(L["Name"])
			)
			:AddChild(TSMAPI_FOUR.UI.NewElement("Text", "sourceColText")
				:SetStyle("font", TSM.UI.Fonts.bold)
				:SetStyle("fontHeight", 18)
				:SetStyle("textColor", "#e2e2e2")
				:SetText(L["Custom Price Source"])
			)
		)
		:AddChildrenWithFunction(private.AddCustomPriceRows)
end

function private.AddCustomPriceRow(frame, name)
	local priceString = TSM.db.global.userData.customPriceSources[name]
	frame:AddChild(TSMAPI_FOUR.UI.NewElement("Frame", "row_"..name)
		:SetLayout("VERTICAL")
		:SetStyle("margin", { left = -10, right = -10 })
		:SetStyle("padding", { left = 10, right = 10 })
		:SetStyle("height", 28)
		:SetMouseEnabled(true)
		:SetContext(name)
		:SetScript("OnMouseDown", private.CustomPriceRowOnMouseDown)
		:AddChild(TSMAPI_FOUR.UI.NewElement("Frame", "textRow")
			:SetLayout("HORIZONTAL")
			:AddChild(TSMAPI_FOUR.UI.NewElement("Frame", "nameFrame")
				:SetLayout("HORIZONTAL")
				:SetStyle("width", NAME_COL_WIDTH)
				:SetStyle("height", 28)
				:AddChild(TSMAPI_FOUR.UI.NewElement("Text", "nameText")
					:SetStyle("height", 28)
					:SetStyle("autoWidth", true)
					:SetStyle("fontHeight", 18)
					:SetStyle("textColor", "#ffffff")
					:SetText(name)
				)
			)
			:AddChild(TSMAPI_FOUR.UI.NewElement("Text", "priceStringText")
				:SetStyle("height", 28)
				:SetStyle("fontHeight", 18)
				:SetStyle("textColor", "#9d9d9d")
				:SetText(priceString)
			)
		)
		:AddChild(TSMAPI_FOUR.UI.NewElement("Frame", "buttonRow")
			:SetLayout("HORIZONTAL")
		)
	)
end

function private.AddCustomPriceRows(frame)
	local names = TSMAPI_FOUR.Util.AcquireTempTable()
	for name in pairs(TSM.db.global.userData.customPriceSources) do
		tinsert(names, name)
	end
	sort(names)
	for _, name in ipairs(names) do
		private.AddCustomPriceRow(frame, name)
	end
end



-- ============================================================================
-- Helper Functions
-- ============================================================================

function private.UpdateSelectedRow(frame)
	-- reset all the rows
	for _, child in frame:LayoutChildrenIterator() do
		local priceName = child:GetContext()
		if priceName then
			local isSelected = priceName == private.selectedRow
			local textRow = child:GetElement("textRow")

			-- remove the old price string element
			local priceStringElement = textRow:GetElement("priceStringText")
			textRow:RemoveChild(priceStringElement)
			priceStringElement:Release()

			-- set general style
			child:SetStyle("background", isSelected and "#6f6f6f" or nil)

			-- remove the old button row children
			local buttonRow = child:GetElement("buttonRow")
			buttonRow:ReleaseAllChildren()

			-- remove the edit button if one exists
			local nameFrame = textRow:GetElement("nameFrame")
			nameFrame:ReleaseAllChildren()

			if isSelected then
				if private.isEditing then
					-- add the input
					nameFrame:AddChild(TSMAPI_FOUR.UI.NewElement("Input", "nameText")
						:SetStyle("height", 28)
						:SetStyle("fontHeight", 18)
						:SetStyle("textColor", "#ffffff")
						:SetFocused(true)
						:SetText(priceName)
						:SetScript("OnEscapePressed", private.NameInputOnEscapePressed)
						:SetScript("OnEnterPressed", private.NameInputOnEnterPressed)
					)
				else
					-- add the text and edit button
					nameFrame:AddChild(TSMAPI_FOUR.UI.NewElement("Text", "nameText")
						:SetStyle("height", 28)
						:SetStyle("autoWidth", true)
						:SetStyle("fontHeight", 18)
						:SetStyle("textColor", "#ffffff")
						:SetText(priceName)
					)
					nameFrame:AddChild(TSMAPI_FOUR.UI.NewElement("Button", "editBtn")
						-- TODO: Set right texture
						:SetStyle("height", 20)
						:SetStyle("width", 20)
						:SetStyle("margin", { left = 10 })
						:SetScript("OnClick", private.EditButtonOnClick)
					)
				end

				-- add the new price string element
				priceStringElement = TSMAPI_FOUR.UI.NewElement("Input", "priceStringText")
					:SetStyle("height", 10000)
					:SetStyle("textColor", "#ffffff")
					:SetMultiLine(true)
					:SetText(TSM.db.global.userData.customPriceSources[priceName])
					:SetScript("OnTextChanged", private.PriceStringInputOnTextChanged)
					:SetScript("OnEscapePressed", private.PriceStringInputOnEscapePressed)
					:SetScript("OnEnterPressed", private.PriceStringInputOnEnterPressed)
				child:SetStyle("height", 10000)
				textRow:AddChild(priceStringElement
					:SetStyle("fontHeight", 18)
				)

				-- fix the height
				textRow:Draw()
				local inputHeight = max(priceStringElement:GetStringHeight(), 28)
				child:SetStyle("height", inputHeight + 39)
				priceStringElement:SetStyle("height", inputHeight)

				-- add the delete button
				buttonRow:AddChild(TSMAPI_FOUR.UI.NewElement("Button", "deleteBtn")
					:SetStyle("borderTexture", "Interface\\Addons\\TradeSkillMaster\\Media\\ButtonEdgeFrame.blp")
					:SetStyle("borderSize", 7)
					:SetStyle("margin", { left = NAME_COL_WIDTH })
					:SetText(DELETE)
					:SetScript("OnClick", private.PriceStringDeleteOnClick)
				)
			else
				-- add the name text
				nameFrame:AddChild(TSMAPI_FOUR.UI.NewElement("Text", "nameText")
					:SetStyle("height", 28)
					:SetStyle("autoWidth", true)
					:SetStyle("fontHeight", 18)
					:SetStyle("textColor", "#ffffff")
					:SetText(priceName)
				)
				-- add the new price string element
				priceStringElement = TSMAPI_FOUR.UI.NewElement("Text", "priceStringText")
					:SetStyle("height", 28)
					:SetStyle("textColor", "#9d9d9d")
					:SetText(TSM.db.global.userData.customPriceSources[priceName])
				child:SetStyle("height", 28)
				textRow:AddChild(priceStringElement
					:SetStyle("fontHeight", 18)
				)
			end
		end
	end
	frame:Draw()
end



-- ============================================================================
-- Local Script Handlers
-- ============================================================================

function private.CustomPriceRowOnMouseDown(self)
	private.selectedRow = self:GetContext()
	private.isEditing = nil
	private.UpdateSelectedRow(self:GetParentElement())
end

function private.PriceStringInputOnTextChanged(self)
	self:SetText(self:GetText())
	local inputHeight = max(self:GetStringHeight(), 28)
	self:SetStyle("height", inputHeight)
	local row = self:GetParentElement():GetParentElement()
	row:SetStyle("height", inputHeight + 30)
	row:GetParentElement():Draw()
end

function private.PriceStringInputOnEscapePressed(self)
	local priceStringName = self:GetParentElement():GetParentElement():GetContext()
	self:SetText(TSM.db.global.userData.customPriceSources[priceStringName])
	self:Draw()
end

function private.PriceStringInputOnEnterPressed(self)
	local priceStringName = self:GetParentElement():GetParentElement():GetContext()
	TSM.db.global.userData.customPriceSources[priceStringName] = strtrim(self:GetText())
end

function private.PriceStringDeleteOnClick(self)
	local row = self:GetParentElement():GetParentElement()
	TSM.CustomPrice.DeleteCustomPriceSource(row:GetContext())

	-- remove this row
	local frame = row:GetParentElement()
	frame:RemoveChild(row)
	row:Release()
	frame:Draw()
end

function private.EditButtonOnClick(self)
	private.isEditing = true
	private.UpdateSelectedRow(self:GetParentElement():GetParentElement():GetParentElement():GetParentElement())
end

function private.NameInputOnEscapePressed(self)
	private.isEditing = nil
	private.UpdateSelectedRow(self:GetParentElement():GetParentElement():GetParentElement():GetParentElement())
end

function private.NameInputOnEnterPressed(self)
	private.isEditing = nil
	local row = self:GetParentElement():GetParentElement():GetParentElement()
	local oldPriceStringName = row:GetContext()
	local newPriceStringName = strtrim(strlower(self:GetText()))

	if newPriceStringName == "" then
		-- pass
	elseif strmatch(newPriceStringName, "[^a-z]") then
		TSM:Print(L["The name can ONLY contain letters. No spaces, numbers, or special characters."])
	elseif TSM.db.global.userData.customPriceSources[newPriceStringName] then
		TSM:Printf(L["Error renaming custom price source. Custom price source with name '%s' already exists."], newPriceStringName)
	else
		row:SetContext(newPriceStringName)
		private.selectedRow = newPriceStringName
		TSM.CustomPrice.RenameCustomPriceSource(oldPriceStringName, newPriceStringName)
	end
	private.UpdateSelectedRow(row:GetParentElement())
end

function private.AddNewButtonOnClick(self)
	local newName = nil
	for i = strbyte("a"), strbyte("z") do
		newName = "customprice"..strchar(i)
		if not TSM.db.global.userData.customPriceSources[newName] then
			break
		end
		newName = nil
	end
	if not newName then
		-- TODO: come up with a better way to avoid name conflicts so we don't need this error
		TSM:Print(L["Could not create a new custom price source. Rename some of your existing ones first."])
		return
	end

	TSM.CustomPrice.CreateCustomPriceSource(newName, "")
	private.selectedRow = newName
	private.isEditing = true
	local frame = self:GetParentElement()
	private.AddCustomPriceRow(frame, newName)
	private.UpdateSelectedRow(frame)
end
