-- ------------------------------------------------------------------------------ --
--                                TradeSkillMaster                                --
--                          https://tradeskillmaster.com                          --
--    All Rights Reserved - Detailed license information included with addon.     --
-- ------------------------------------------------------------------------------ --

local _, TSM = ...
local Groups = TSM.UI.MailingUI:NewPackage("Groups")
local L = TSM.Include("Locale").GetTable()
local FSM = TSM.Include("Util.FSM")
local Log = TSM.Include("Util.Log")
local Settings = TSM.Include("Service.Settings")
local UIElements = TSM.Include("UI.UIElements")
local private = {
	settings = nil,
	filterText = "",
	fsm = nil
}
local SECONDS_PER_MINUTE = 60



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

function Groups.OnInitialize()
	private.settings = Settings.NewView()
		:AddKey("char", "mailingUIContext", "groupTree")
		:AddKey("global", "mailingOptions", "resendDelay")
	private.FSMCreate()
	TSM.UI.MailingUI.RegisterTopLevelPage(L["Groups"], private.GetGroupsFrame)
end



-- ============================================================================
-- Groups UI
-- ============================================================================

function private.GetGroupsFrame()
	TSM.UI.AnalyticsRecordPathChange("mailing", "groups")
	return UIElements.New("Frame", "groups")
		:SetLayout("VERTICAL")
		:AddChild(UIElements.New("Frame", "container")
			:SetLayout("VERTICAL")
			:SetPadding(8)
			:SetBackgroundColor("PRIMARY_BG")
			:AddChild(UIElements.New("Frame", "search")
				:SetLayout("HORIZONTAL")
				:SetHeight(24)
				:AddChild(UIElements.New("Input", "input")
					:SetIconTexture("iconPack.18x18/Search")
					:SetClearButtonEnabled(true)
					:AllowItemInsert(true)
					:SetHintText(L["Search Groups"])
					:SetValue(private.filterText)
					:SetScript("OnValueChanged", private.GroupSearchOnValueChanged)
				)
				:AddChild(UIElements.New("Button", "expandAllBtn")
					:SetSize(24, 24)
					:SetMargin(8, 4, 0, 0)
					:SetBackground("iconPack.18x18/Expand All")
					:SetScript("OnClick", private.ExpandAllGroupsOnClick)
					:SetTooltip(L["Expand / Collapse All Groups"])
				)
				:AddChild(UIElements.New("Button", "selectAllBtn")
					:SetSize(24, 24)
					:SetBackground("iconPack.18x18/Select All")
					:SetScript("OnClick", private.SelectAllGroupsOnClick)
					:SetTooltip(L["Select / Deselect All Groups"])
				)
			)
		)
		:AddChild(UIElements.New("Texture", "line")
			:SetHeight(2)
			:SetTexture("ACTIVE_BG")
		)
		:AddChild(UIElements.New("ApplicationGroupTree", "groupTree")
			:SetMargin(0, 0, 0, 1)
			:SetSettingsContext(private.settings, "groupTree")
			:SetQuery(TSM.Groups.CreateQuery(), "Mailing")
			:SetSearchString(private.filterText)
			:SetScript("OnGroupSelectionChanged", private.GroupTreeOnGroupSelectionChanged)
		)
		:AddChild(UIElements.New("Frame", "footer")
			:SetLayout("HORIZONTAL")
			:SetHeight(26)
			:SetBackgroundColor("PRIMARY_BG")
			:AddChild(UIElements.New("Spacer", "spacer"))
			:AddChild(UIElements.New("Text", "groupsText")
				:SetFont("BODY_BODY2_MEDIUM")
				:SetJustifyH("RIGHT")
				:SetText(format(L["%d Groups Selected"], 0))
			)
			:AddChild(UIElements.New("Texture", "vline")
				:SetWidth(1)
				:SetMargin(8, 8, 2, 2)
				:SetTexture("ACTIVE_BG_ALT")
			)
			:AddChild(UIElements.New("Text", "itemsText")
				:SetWidth("AUTO")
				:SetMargin(0, 8, 0, 0)
				:SetFont("BODY_BODY2_MEDIUM")
				:SetJustifyH("RIGHT")
				:SetText(L["Total Items"]..": ".."0")
			)
		)
		:AddChild(UIElements.New("Texture", "line")
			:SetHeight(2)
			:SetTexture("ACTIVE_BG")
		)
		:AddChild(UIElements.New("Frame", "bottom")
			:SetLayout("VERTICAL")
			:SetHeight(40)
			:SetPadding(8)
			:SetBackgroundColor("PRIMARY_BG_ALT")
			:AddChild(UIElements.New("ActionButton", "mailGroupBtn")
				:SetHeight(24)
				:SetText(L["Mail Selected Groups"])
				:SetScript("OnClick", private.MailBtnOnClick)
				:SetModifierText(L["Mail Selected Groups (Dry Run)"], "CTRL")
				:SetModifierText(L["Mail Selected Groups (Auto Resend)"], "SHIFT")
				:SetModifierText(L["Mail Selected Groups (Dry Run + Auto Resend)"], "SHIFT", "CTRL")
				:SetTooltip(format(L["Hold SHIFT to automatically resend items after '%s', and CTRL to perform a dry-run where no items are actually mailed, but chat messages will still display the result."], SecondsToTime(private.settings.resendDelay * SECONDS_PER_MINUTE)))
			)
		)
		:SetScript("OnUpdate", private.FrameOnUpdate)
		:SetScript("OnHide", private.FrameOnHide)
end



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

function private.FrameOnUpdate(frame)
	frame:SetScript("OnUpdate", nil)
	private.GroupTreeOnGroupSelectionChanged(frame:GetElement("groupTree"))
	private.fsm:ProcessEvent("EV_FRAME_SHOW", frame)
end

function private.FrameOnHide(frame)
	private.fsm:ProcessEvent("EV_FRAME_HIDE")
end

function private.GroupSearchOnValueChanged(input)
	local text = strlower(input:GetValue())
	if text == private.filterText then
		return
	end
	private.filterText = text

	input:GetElement("__parent.__parent.__parent.groupTree")
		:SetSearchString(private.filterText)
		:Draw()
end

function private.ExpandAllGroupsOnClick(button)
	button:GetElement("__parent.__parent.__parent.groupTree")
		:ToggleExpandAll()
end

function private.SelectAllGroupsOnClick(button)
	button:GetElement("__parent.__parent.__parent.groupTree")
		:ToggleSelectAll()
end

function private.GroupTreeOnGroupSelectionChanged(groupTree)
	groupTree:GetElement("__parent.bottom.mailGroupBtn")
		:SetDisabled(groupTree:IsSelectionCleared())
		:Draw()

	local numGroups, numItems = 0, 0
	for _, groupPath in groupTree:SelectedGroupsIterator() do
		numGroups = numGroups + 1
		if groupPath == TSM.CONST.ROOT_GROUP_PATH then
			-- TODO
		else
			for _ in TSM.Groups.ItemIterator(groupPath) do
				numItems = numItems + 1
			end
		end
	end
	groupTree:GetElement("__parent.footer.groupsText")
		:SetText(format(L["%d Groups Selected"], numGroups))
	groupTree:GetElement("__parent.footer.itemsText")
		:SetText(L["Total Items"]..": "..numItems)

	groupTree:GetElement("__parent.footer")
		:Draw()
end

function private.MailBtnOnClick(button)
	private.fsm:ProcessEvent("EV_BUTTON_CLICKED", IsShiftKeyDown(), IsControlKeyDown())
end



-- ============================================================================
-- FSM
-- ============================================================================

function private.FSMCreate()
	local fsmContext = {
		frame = nil,
		sending = false
	}

	local function UpdateButton(context)
		context.frame:GetElement("bottom.mailGroupBtn")
			:SetText(context.sending and L["Sending..."] or L["Mail Selected Groups"])
			:SetPressed(context.sending)
			:Draw()
	end

	private.fsm = FSM.New("MAILING_GROUPS")
		:AddState(FSM.NewState("ST_HIDDEN")
			:SetOnEnter(function(context)
				TSM.Mailing.Send.KillThread()
				TSM.Mailing.Groups.KillThread()
				context.frame = nil
			end)
			:AddTransition("ST_SHOWN")
			:AddTransition("ST_HIDDEN")
			:AddEventTransition("EV_FRAME_SHOW", "ST_SHOWN")
		)
		:AddState(FSM.NewState("ST_SHOWN")
			:SetOnEnter(function(context, frame)
				if not context.frame then
					context.frame = frame
				end
				UpdateButton(context)
			end)
			:AddTransition("ST_HIDDEN")
			:AddTransition("ST_SENDING_START")
			:AddEventTransition("EV_BUTTON_CLICKED", "ST_SENDING_START")
		)
		:AddState(FSM.NewState("ST_SENDING_START")
			:SetOnEnter(function(context, sendRepeat, isDryRun)
				context.sending = true
				local groups = {}
				for _, groupPath in context.frame:GetElement("groupTree"):SelectedGroupsIterator() do
					tinsert(groups, groupPath)
				end
				if isDryRun then
					Log.PrintUser(L["Performing a dry-run of your Mailing operations for the selected groups."])
				end
				TSM.Mailing.Groups.StartSending(private.FSMGroupsCallback, groups, sendRepeat, isDryRun)
				UpdateButton(context)
			end)
			:SetOnExit(function(context)
				context.sending = false
			end)
			:AddTransition("ST_SHOWN")
			:AddTransition("ST_HIDDEN")
			:AddEventTransition("EV_SENDING_DONE", "ST_SHOWN")
		)
		:AddDefaultEventTransition("EV_FRAME_HIDE", "ST_HIDDEN")
		:Init("ST_HIDDEN", fsmContext)
end

function private.FSMGroupsCallback()
	private.fsm:ProcessEvent("EV_SENDING_DONE")
end
