local _, ns = ...
local B, C, L, DB = unpack(ns)
local M = B:GetModule("Misc")

local wipe, select, pairs, tonumber = wipe, select, pairs, tonumber
local strsplit, strfind, tinsert = strsplit, strfind, tinsert
local InboxItemCanDelete, DeleteInboxItem, TakeInboxMoney, TakeInboxItem = InboxItemCanDelete, DeleteInboxItem, TakeInboxMoney, TakeInboxItem
local GetInboxNumItems, GetInboxHeaderInfo, GetInboxItem = GetInboxNumItems, GetInboxHeaderInfo, GetInboxItem
local GetSendMailPrice, GetMoney = GetSendMailPrice, GetMoney
local C_Timer_After = C_Timer.After
local C_Mail_HasInboxMoney = C_Mail.HasInboxMoney
local C_Mail_IsCommandPending = C_Mail.IsCommandPending
local ATTACHMENTS_MAX_RECEIVE, ERR_MAIL_DELETE_ITEM_ERROR = ATTACHMENTS_MAX_RECEIVE, ERR_MAIL_DELETE_ITEM_ERROR
local NORMAL_STRING = GUILDCONTROL_OPTION16
local OPENING_STRING = OPEN_ALL_MAIL_BUTTON_OPENING

local mailIndex, timeToWait, totalCash, inboxItems = 0, .15, 0, {}
local isGoldCollecting

function M:MailBox_DelectClick()
	local selectedID = self.id + (InboxFrame.pageNum-1)*7
	if InboxItemCanDelete(selectedID) then
		DeleteInboxItem(selectedID)
	else
		UIErrorsFrame:AddMessage(DB.InfoColor..ERR_MAIL_DELETE_ITEM_ERROR)
	end
end

function M:MailItem_AddDelete(i)
	local bu = CreateFrame("Button", nil, self)
	bu:SetPoint("BOTTOMRIGHT", self:GetParent(), "BOTTOMRIGHT", -8, 6)
	bu:SetSize(14, 14)
	B.PixelIcon(bu, 136813, true)
	bu.id = i
	bu:SetScript("OnClick", M.MailBox_DelectClick)
	B.AddTooltip(bu, "ANCHOR_RIGHT", DELETE, "system")
end

function M:InboxItem_OnEnter()
	if not self.index then return end -- may receive fake mails from Narcissus
	wipe(inboxItems)

	local itemAttached = select(8, GetInboxHeaderInfo(self.index))
	if itemAttached then
		for attachID = 1, 12 do
			local _, itemID, _, itemCount = GetInboxItem(self.index, attachID)
			if itemCount and itemCount > 0 then
				inboxItems[itemID] = (inboxItems[itemID] or 0) + itemCount
			end
		end

		if itemAttached > 1 then
			GameTooltip:AddLine(L["Attach List"])
			for itemID, count in pairs(inboxItems) do
				local itemName, _, itemQuality, _, _, _, _, _, _, itemTexture = C_Item.GetItemInfo(itemID)
				if itemName then
					local r, g, b = C_Item.GetItemQualityColor(itemQuality)
					GameTooltip:AddDoubleLine(" |T"..itemTexture..":12:12:0:0:50:50:4:46:4:46|t "..itemName, count, r, g, b)
				end
			end
			GameTooltip:Show()
		end
	end
end

local contactList = {}
local contactListByRealm = {}

function M:ContactButton_OnClick()
	local text = self.name:GetText() or ""
	text = Ambiguate(text, "none")
	SendMailNameEditBox:SetText(text)
	SendMailNameEditBox:SetCursorPosition(0)
end

function M:ContactButton_Delete()
	OrzUISetDB["ContactList"][self.__owner.name:GetText()] = nil
	M:ContactList_Refresh()
end

function M:ContactButton_Create(parent, index)
	local button = CreateFrame("Button", nil, parent)
	button:SetSize(150, 20)
	button:SetPoint("TOPLEFT", 2, -2 - (index-1) *20)
	button.HL = button:CreateTexture(nil, "HIGHLIGHT")
	button.HL:SetAllPoints()
	button.HL:SetColorTexture(1, 1, 1, .25)

	button.name = B.CreateFS(button, 13, "Name", false, "LEFT", 0, 0)
	button.name:SetPoint("RIGHT", button, "LEFT", 155, 0)
	button.name:SetJustifyH("LEFT")

	button:RegisterForClicks("AnyUp")
	button:SetScript("OnClick", M.ContactButton_OnClick)

	button.delete = B.CreateButton(button, 20, 20, true, "Atlas:common-icon-redx")
	button.delete:SetPoint("LEFT", button, "RIGHT", 2, 0)
	button.delete.__owner = button
	button.delete:SetScript("OnClick", M.ContactButton_Delete)

	return button
end

local function GenerateDataByRealm(realm)
	if contactListByRealm[realm] then
		for name, color in pairs(contactListByRealm[realm]) do
			local r, g, b = strsplit(":", color)
			tinsert(contactList, {name = name.."-"..realm, r = r, g = g, b = b})
		end
	end
end

function M:ContactList_Refresh()
	wipe(contactList)
	wipe(contactListByRealm)

	for fullname, color in pairs(OrzUISetDB["ContactList"]) do
		local name, realm = strmatch(fullname, "^(.-)%-(.*)$")
		if realm then
			if not contactListByRealm[realm] then contactListByRealm[realm] = {} end
			contactListByRealm[realm][name] = color
		end
	end

	GenerateDataByRealm(DB.MyRealm)

	for realm in pairs(contactListByRealm) do
		if realm ~= DB.MyRealm then
			GenerateDataByRealm(realm)
		end
	end

	M:ContactList_Update()
end

function M:ContactButton_Update(button)
	local index = button.index
	local info = contactList[index]

	button.name:SetText(info.name)
	button.name:SetTextColor(info.r, info.g, info.b)
end

function M:ContactList_Update()
	local scrollFrame = _G.OrzUIMailBoxScrollFrame
	local usedHeight = 0
	local buttons = scrollFrame.buttons
	local height = scrollFrame.buttonHeight
	local numFriendButtons = #contactList
	local offset = HybridScrollFrame_GetOffset(scrollFrame)

	for i = 1, #buttons do
		local button = buttons[i]
		local index = offset + i
		if index <= numFriendButtons then
			button.index = index
			M:ContactButton_Update(button)
			usedHeight = usedHeight + height
			button:Show()
		else
			button.index = nil
			button:Hide()
		end
	end

	HybridScrollFrame_Update(scrollFrame, numFriendButtons*height, usedHeight)
end

function M:ContactList_OnMouseWheel(delta)
	local scrollBar = self.scrollBar
	local step = delta*self.buttonHeight
	if IsShiftKeyDown() then
		step = step*18
	end
	scrollBar:SetValue(scrollBar:GetValue() - step)
	M:ContactList_Update()
end

function M:MailBox_ContactList()
	local bu = B.CreateGear(SendMailFrame)
	bu:SetPoint("LEFT", SendMailNameEditBox, "RIGHT", 21, 0)

	local list = CreateFrame("Frame", nil, bu)
	list:SetSize(200, 424)
	list:SetPoint("TOPLEFT", MailFrame, "TOPRIGHT", 3, -C.mult)
	list:SetFrameStrata("Tooltip")
	B.SetBD(list)
	B.CreateFS(list, 14, L["ContactList"], "system", "TOP", 0, -5)

	bu:SetScript("OnClick", function()
		B:TogglePanel(list)
	end)

	local editbox = B.CreateEditBox(list, 120, 20)
	editbox:SetPoint("TOPLEFT", 5, -25)
	B.AddTooltip(editbox, "ANCHOR_BOTTOMRIGHT", L["AddContactTip"], "info", true)
	local swatch = B.CreateColorSwatch(list, "")
	swatch:SetPoint("LEFT", editbox, "RIGHT", 5, 0)
	local add = B.CreateButton(list, 42, 22, ADD, 14)
	add:SetPoint("LEFT", swatch, "RIGHT", 5, 0)
	add:SetScript("OnClick", function()
		local text = editbox:GetText()
		if text == "" or tonumber(text) then return end -- incorrect input
		if not strfind(text, "-") then text = text.."-"..DB.MyRealm end -- complete player realm name
		if OrzUISetDB["ContactList"][text] then return end -- unit exists

		local r, g, b = swatch.tex:GetColor()
		OrzUISetDB["ContactList"][text] = r..":"..g..":"..b
		M:ContactList_Refresh()
		editbox:SetText("")
	end)

	local scrollFrame = CreateFrame("ScrollFrame", "OrzUIMailBoxScrollFrame", list, "HybridScrollFrameTemplate")
	scrollFrame:SetSize(175, 370)
	scrollFrame:SetPoint("BOTTOMLEFT", 5, 5)
	B.CreateBDFrame(scrollFrame, .25)
	list.scrollFrame = scrollFrame

	local scrollBar = CreateFrame("Slider", "$parentScrollBar", scrollFrame, "HybridScrollBarTemplate")
	scrollBar.doNotHide = true
	B.ReskinScroll(scrollBar)
	scrollFrame.scrollBar = scrollBar

	local scrollChild = scrollFrame.scrollChild
	local numButtons = 19 + 1
	local buttonHeight = 22
	local buttons = {}
	for i = 1, numButtons do
		buttons[i] = M:ContactButton_Create(scrollChild, i)
	end

	scrollFrame.buttons = buttons
	scrollFrame.buttonHeight = buttonHeight
	scrollFrame.update = M.ContactList_Update
	scrollFrame:SetScript("OnMouseWheel", M.ContactList_OnMouseWheel)
	scrollChild:SetSize(scrollFrame:GetWidth(), numButtons * buttonHeight)
	scrollFrame:SetVerticalScroll(0)
	scrollFrame:UpdateScrollChildRect()
	scrollBar:SetMinMaxValues(0, numButtons * buttonHeight)
	scrollBar:SetValue(0)

	M:ContactList_Refresh()
end

function M:MailBox_CollectGold()
	if mailIndex > 0 then
		if not C_Mail_IsCommandPending() then
			if C_Mail_HasInboxMoney(mailIndex) then
				TakeInboxMoney(mailIndex)
			end
			mailIndex = mailIndex - 1
		end
		C_Timer_After(timeToWait, M.MailBox_CollectGold)
	else
		isGoldCollecting = false
		M:UpdateOpeningText()
	end
end

function M:MailBox_CollectAllGold()
	if isGoldCollecting then return end
	if totalCash == 0 then return end

	isGoldCollecting = true
	mailIndex = GetInboxNumItems()
	M:UpdateOpeningText(true)
	M:MailBox_CollectGold()
end

function M:TotalCash_OnEnter()
	local numItems = GetInboxNumItems()
	if numItems == 0 then return end

	for i = 1, numItems do
		totalCash = totalCash + select(5, GetInboxHeaderInfo(i))
	end

	if totalCash > 0 then
		GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
		GameTooltip:AddLine(L["TotalGold"])
		GameTooltip:AddLine(" ")
		GameTooltip:AddLine(M:GetMoneyString(totalCash, true), 1,1,1)
		GameTooltip:Show()
	end
end

function M:TotalCash_OnLeave()
	B:HideTooltip()
	totalCash = 0
end

function M:UpdateOpeningText(opening)
	if opening then
		M.GoldButton:SetText(OPENING_STRING)
	else
		M.GoldButton:SetText(NORMAL_STRING)
	end
end

function M:MailBox_CreatButton(parent, width, height, text, anchor)
	local button = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
	button:SetSize(width, height)
	button:SetPoint(unpack(anchor))
	button:SetText(text)

	return button
end

function M:CollectGoldButton()
	OpenAllMail:ClearAllPoints()
	OpenAllMail:SetPoint("TOPLEFT", InboxFrame, "TOPLEFT", 50, -30)

	local button = M:MailBox_CreatButton(InboxFrame, 80, 25, "", {"LEFT", OpenAllMail, "RIGHT", 0, 0})
	button:SetScript("OnClick", M.MailBox_CollectAllGold)
	button:HookScript("OnEnter", M.TotalCash_OnEnter)
	button:HookScript("OnLeave", M.TotalCash_OnLeave)

	M.GoldButton = button
	M:UpdateOpeningText()
	
	-------DelMailbutton----------------
	local DelMailbutton = M:MailBox_CreatButton(InboxFrame, 80, 25, "", {"LEFT", button, "RIGHT", 0, 0})
	DelMailbutton:SetText(MAIL_DELETEEMPTYMAILS)
	DelMailbutton:SetScript("OnClick", function() SenduiCmd("/mbclean") end)
end

function M:MailBox_CollectAttachment()
	for i = 1, ATTACHMENTS_MAX_RECEIVE do
		local attachmentButton = OpenMailFrame.OpenMailAttachments[i]
		if attachmentButton:IsShown() then
			TakeInboxItem(InboxFrame.openMailID, i)
			C_Timer_After(timeToWait, M.MailBox_CollectAttachment)
			return
		end
	end
end

function M:MailBox_CollectCurrent()
	if OpenMailFrame.cod then
		UIErrorsFrame:AddMessage(DB.InfoColor..L["MailIsCOD"])
		return
	end

	local currentID = InboxFrame.openMailID
	if C_Mail_HasInboxMoney(currentID) then
		TakeInboxMoney(currentID)
	end
	M:MailBox_CollectAttachment()
end

function M:CollectCurrentButton()
	local button = M:MailBox_CreatButton(OpenMailFrame, 82, 22, L["TakeAll"], {"RIGHT", "OpenMailReplyButton", "LEFT", -1, 0})
	button:SetScript("OnClick", M.MailBox_CollectCurrent)
end

function M:LastMailSaver()
	local mailSaver = CreateFrame("CheckButton", nil, SendMailFrame, "OptionsBaseCheckButtonTemplate")
	mailSaver:SetHitRectInsets(0, 0, 0, 0)
	mailSaver:SetPoint("LEFT", SendMailNameEditBox, "RIGHT", 0, 0)
	mailSaver:SetSize(24, 24)
	--B.ReskinCheck(mailSaver)
	--mailSaver.bg:SetBackdropBorderColor(1, .8, 0, .5)

	mailSaver:SetChecked(C.db["Misc"]["MailSaver"])
	mailSaver:SetScript("OnClick", function(self)
		C.db["Misc"]["MailSaver"] = self:GetChecked()
	end)
	B.AddTooltip(mailSaver, "ANCHOR_TOP", L["SaveMailTarget"])

	local resetPending
	hooksecurefunc("SendMailFrame_SendMail", function()
		if C.db["Misc"]["MailSaver"] then
			C.db["Misc"]["MailTarget"] = SendMailNameEditBox:GetText()
			resetPending = true
		else
			resetPending = nil
		end
	end)

	hooksecurefunc(SendMailNameEditBox, "SetText", function(self, text)
		if resetPending and text == "" then
			resetPending = nil
			self:SetText(C.db["Misc"]["MailTarget"])
		end
	end)

	SendMailFrame:HookScript("OnShow", function()
		if C.db["Misc"]["MailSaver"] then
			SendMailNameEditBox:SetText(C.db["Misc"]["MailTarget"])
		end
	end)
end

function M:ArrangeDefaultElements()
	InboxTooMuchMail:ClearAllPoints()
	InboxTooMuchMail:SetPoint("BOTTOM", MailFrame, "TOP", 0, 5)

	SendMailNameEditBox:SetWidth(155)
	SendMailNameEditBoxMiddle:SetWidth(146)
	SendMailCostMoneyFrame:SetAlpha(0)

	SendMailMailButton:HookScript("OnEnter", function(self)
		GameTooltip:SetOwner(self, "ANCHOR_TOP")
		GameTooltip:ClearLines()
		local sendPrice = GetSendMailPrice()
		local colorStr = "|cffffffff"
		if sendPrice > GetMoney() then colorStr = "|cffff0000" end
		GameTooltip:AddLine(SEND_MAIL_COST..colorStr..M:GetMoneyString(sendPrice, true))
		GameTooltip:Show()
	end)
	SendMailMailButton:HookScript("OnLeave", B.HideTooltip)
end

function M:MailBox()
	if not C.db["Misc"]["Mail"] then return end
	if C_AddOns.IsAddOnLoaded("Postal") then return end

	-- Delete buttons
	for i = 1, 7 do
		local itemButton = _G["MailItem"..i.."Button"]
		M.MailItem_AddDelete(itemButton, i)
	end

	-- Tooltips for multi-items
	hooksecurefunc("InboxFrameItem_OnEnter", M.InboxItem_OnEnter)

	-- Custom contact list
	M:MailBox_ContactList()

	-- Elements
	M:ArrangeDefaultElements()
	M.GetMoneyString = B:GetModule("Infobar").GetMoneyString
	M:CollectGoldButton()
	M:CollectCurrentButton()
	M:LastMailSaver()
end
M:RegisterMisc("MailBox", M.MailBox)

-- LockboxMailer ## Version: 0.1.14
local LockboxMailer = CreateFrame("Frame")
LockboxMailer:RegisterEvent("PLAYER_LOGIN")
LockboxMailer:SetScript("OnEvent", function(event, ...) LockboxMailer.LockboxTable = {} end)  
local LockBoxButton = CreateFrame("Button", "LockBoxMailButton", SendMailFrame, "ActionButtonTemplate")
LockBoxButton:ClearAllPoints()
LockBoxButton:SetPoint("BOTTOMRIGHT", SendMailFrame, "BOTTOMRIGHT", -66, 123)
LockBoxButton:SetSize(26,26)
    if LE_EXPANSION_LEVEL_CURRENT >= 9 then
        LockBoxButton.HighlightTexture:SetSize(26,27)
        LockBoxButton.PushedTexture:SetSize(28,28)
    end
LockBoxButton:RegisterForClicks("AnyUp")
LockBoxButton:SetScript("OnClick", function(_,btn) LockboxMailer:ProcessMailing() end)
LockBoxButton.icon:SetTexture(134344)
LockBoxButton.NormalTexture:ClearAllPoints()

if not C_TooltipInfo then
    LockboxMailer.tooltip = CreateFrame("GameTooltip","LockboxMailerTooltip", UIParent);
    LockboxMailer.tooltip:SetOwner(LockboxMailer, "ANCHOR_NONE");
end

function LockboxMailer:ScanTooltip(bag, slot)
    if C_TooltipInfo then
        local tooltipData = C_TooltipInfo.GetBagItem(bag, slot)
        for i = 1, #tooltipData.lines do
            local line = tooltipData.lines[i].leftText
            if (line == LOCKED) or (line == ITEM_OPENABLE) then
                tinsert(self.LockboxTable, { bag, slot } )
                break
            end
        end
    else
        self.tooltip:SetBagItem(bag, slot)
        if self.tooltip:IsShown() then
            for i = 1, self.tooltip:NumLines() do
                local line = _G[self.tooltip:GetName().."TextLeft"..i]:GetText()
                if (line == LOCKED) or (line == ITEM_OPENABLE) then
                    tinsert(self.LockboxTable, { bag, slot } )
                    break
                end
            end
        end
    end
end

function LockboxMailer:FindLockboxes()
    wipe(LockboxMailer.LockboxTable)
    for bag = BACKPACK_CONTAINER, NUM_BAG_SLOTS do
        for slot = 1, C_Container.GetContainerNumSlots(bag) do
            local containerInfo = C_Container.GetContainerItemInfo(bag, slot)
            if containerInfo and containerInfo.hasLoot then
                local itemLink = containerInfo.hyperlink
                if itemLink then
                    local bindType = select(14, C_Item.GetItemInfo(itemLink))
                    if bindType ~= 1 then
                        self:ScanTooltip(bag, slot)
                    end
                end
            end
        end
    end
end

function LockboxMailer:ProcessMailing()
        --ClearSendMail()
        --SendMailNameEditBox:SetText("烂柯人")
    local attachmentIndex = 0
    for i = 1, ATTACHMENTS_MAX_SEND do
        if GetSendMailItem(i) then
            attachmentIndex = attachmentIndex + 1
        end
    end

    if attachmentIndex < ATTACHMENTS_MAX_SEND then
        LockboxMailer:FindLockboxes()
    end

    local quantity = #LockboxMailer.LockboxTable
    if next(LockboxMailer.LockboxTable) then
        attachmentIndex = (attachmentIndex == 0 and 1 or attachmentIndex + 1)
        for i = 1, quantity do
            local item = tremove(LockboxMailer.LockboxTable)
            if attachmentIndex == ATTACHMENTS_MAX_SEND then
                UIErrorsFrame:AddMessage(ERR_MAIL_INVALID_ATTACHMENT_SLOT, 1.0, 0.1, 0.1, 1.0)
                return
            end
            ClearCursor()
            C_Container.PickupContainerItem(item[1], item[2])
            ClickSendMailItemButton()
            attachmentIndex = attachmentIndex + 1
        end
            SendMailSubjectEditBox:SetText("["..quantity.."]")
        end
end

-------MailinputboxResizer---------------------------------------------------------------
SendMailCostMoneyFrame:ClearAllPoints()
SendMailCostMoneyFrame:SetPoint("TOPLEFT","SendMailFrame","TOPLEFT",82,-70)
_G["SendMailNameEditBox"]:SetSize(228,21)				----EditBox width default: 224
_G["SendMailNameEditBoxRight"]:ClearAllPoints()
_G["SendMailNameEditBoxRight"]:SetPoint("TOPRIGHT",0,0)
_G["SendMailNameEditBoxMiddle"]:SetSize(0,21)
_G["SendMailNameEditBoxMiddle"]:ClearAllPoints()
_G["SendMailNameEditBoxMiddle"]:SetPoint("LEFT","SendMailNameEditBoxLeft","LEFT",3,0)
_G["SendMailNameEditBoxMiddle"]:SetPoint("RIGHT",_G["SendMailNameEditBoxRight"],"RIGHT",-3,0)

-- Mailbox Cleaner-------- by Jadya - EU-Well of Eternity---------------------------------
local title = GEAR_DELETEEMPTYMAILS_TITLE
local em_enabled = false
local timeout = 0
local MailboxCleaner = CreateFrame("Frame")
local options_desc = { ["read"] = "Delete unread mails" }

local function endloop()
 em_enabled = false
 MailboxCleaner:Hide()
 print(title.." - Done.")
end

local function update()
 if not em_enabled or not InboxFrame or not InboxFrame:IsVisible() then endloop() return end
 local num = GetInboxNumItems()
 if num < 1 or i < 1 then
  endloop()
  return
 end
 local t = time()
 if timeout > 0 then
  if i > num or (timeout < t) then
   i = math.min(i - 1, num)
   timeout = 0
  else
   return
  end
 end

 --if InboxItemCanDelete(i) then
 local packageIcon, stationeryIcon, sender, subject, money, CODAmount, daysLeft, itemCount, wasRead, wasReturned, textCreated, canReply, isGM, itemQuantity = GetInboxHeaderInfo(i)
 if (ShiGuangDB["MailRead"] or wasRead) and not isGM and (not snd or (snd and (snd == string.lower(sender)))) and (not itemCount or itemCount == 0) and (not money or money == 0) then
  DeleteInboxItem(i)
  timeout = t + 1
 else
  i = i - 1
 end   
 --end
 if i > num then 
  endloop()
 end
end

MailboxCleaner:SetScript("OnUpdate", update)
MailboxCleaner:Hide()

local function printOptionMsg(arg, help)
 if ShiGuangDB[arg] == nil then return end
 print(title.." - "..(options_desc[arg] or "<unknown>").." = |cff69CCF0"..tostring(ShiGuangDB[arg]).."|r".. (help and " (|cffCCCCCC/mbclean "..arg.."|r)" or ""))
end

local function start(arg)
 if arg == "MailRead" then
  ShiGuangDB["MailRead"] = not ShiGuangDB["MailRead"]
  printOptionMsg(arg)
  return
 end

 if not InboxFrame or not InboxFrame:IsVisible() then
  print(title..MAIL_OPENMAILBOX)
  return
 end
 if arg and arg ~= "" then
  snd = string.lower(arg)
 else
  snd = nil
 end
 i = GetInboxNumItems()
 print(title.." - Doing"..(snd and " from "..snd or "").."...")
 em_enabled = true
 MailboxCleaner:Show()
end

local eventframe = CreateFrame("Frame")
eventframe:RegisterEvent("PLAYER_ENTERING_WORLD")
eventframe:SetScript("OnEvent", function() printOptionMsg("...", true) eventframe:SetScript("OnEvent", nil) end)
-- slash command
SLASH_MAILBOXCLEANER1 = "/mbclean"
SLASH_MAILBOXCLEANER2 = "/mailboxcleaner"
SlashCmdList["MAILBOXCLEANER"] = start