local ADDON_NAME, BigBrother = ...

_G.BigBrother = LibStub("AceAddon-3.0"):NewAddon(BigBrother, "BigBrother", "AceEvent-3.0", "AceHook-3.0")
BigBrother:SetDefaultModuleLibraries("AceEvent-3.0")

local L = LibStub("AceLocale-3.0"):GetLocale("BigBrother")

local _G = _G

local optionsFrame
local function GetOptions()
	local db = BigBrother.db.profile
	local options = {
		name = ADDON_NAME,
		type = "group",
		childGroups = "tab",
		args = {
			confdesc = {
				name = GetAddOnMetadata("BigBrother", "Notes").."\n",
				type = "description",
				order = 1,
				width = "full",
			},
			autogroups = {
				name = L["Checked Raid Groups"],
				--desc = L["Set which raid groups are checked for buffs."],
				type = "group",
				inline = true,
				order = 20,
				hidden = function(info) return info[#info] ~= "autogroups" and db.autogroups end,
				args = {
					autogroups = {
						name = L["Use Instance Difficulty"],
						desc = L["Use the currently selected instance difficulty to determine which groups to check."],
						type = "toggle",
						get = function() return db.autogroups end,
						set = function(info, value) db.autogroups = value end,
						width = "full",
						order = 1,
					},
				},
			},
		},
	}

	for i=1,8 do
		options.args.autogroups.args["group"..i] = {
			name = _G.GROUP_NUMBER:format(i),
			type = "toggle",
			get = function() return db.groups[i] end,
			set = function(info, value) db.groups[i] = value end,
			order = 10 + i,
		}
	end

	for _, module in BigBrother:IterateModules() do
		if module.AddOptions then
			module:AddOptions(options)
		end
	end

	options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(BigBrother.db)
	options.args.profile.desc = nil
	options.args.profile.order = 100

	return options
end

function BigBrother:OnInitialize()
	self.db = LibStub("AceDB-3.0"):New("BigBrotherDB", {
		profile = {
			autogroups = true,
			groups = { true, true, true, true, true, false, false, false },
		}
	}, true)

	LibStub("AceConfig-3.0"):RegisterOptionsTable("BigBrother", GetOptions)
	LibStub("AceConfigDialog-3.0"):AddToBlizOptions("BigBrother")

	--raw hook otherwise SetItemRef will also fire on other |H's in the message
	self:RawHook("SetItemRef", function(link, ...)
		if strsub(link, 1, 10) ~= "bigbrother" then
			return self.hooks["SetItemRef"](link, ...)
		end
		if not IsShiftKeyDown() then return end

		local _, msg = strsplit(":", link, 2)
		msg = msg:gsub("@", "|")
		local editBox = ChatEdit_ChooseBoxForSend()
		if editBox:IsShown() and editBox:GetText() ~= "" then
			editBox:Insert(" "..msg)
		else
			ChatEdit_ActivateChat(editBox)
			editBox:SetText(msg)
		end
	end, true)
end

function BigBrother:OnEnable()
	self:RegisterEvent("CHANNEL_UI_UPDATE")
	self:RegisterEvent("PLAYER_ENTERING_WORLD", "CHANNEL_UI_UPDATE")
end

function BigBrother:Print(...)
	print("|cff33ff99BigBrother|r:", tostringall(...))
end

function BigBrother:GetInstanceSize()
	local _, instanceType, diff = GetInstanceInfo()
	if instanceType == "party" or instanceType == "arena" then
		return 5
	elseif instanceType == "none" or instanceType == "pvp" or diff == 9 then
		return 40
	elseif diff == 3 or diff == 5 then -- 10 player
		return 10
	elseif diff == 4 or diff == 6 or diff == 7 then -- 25 player
		return 25
	elseif diff == 14 or diff == 15 or diff == 17 then -- Flex
		return 30
	elseif diff == 16 then -- Mythic
		return 20
	else
		return 40
	end
end

do -- BigBrother:GetCheckedGroups()
	local groups = {
		[5]  = { true },
		[10] = { true, true },
		[20] = { true, true, true, true },
		[25] = { true, true, true, true, true },
		[30] = { true, true, true, true, true, true },
		[40] = { true, true, true, true, true, true, true, true }
	}

	function BigBrother:GetCheckedGroups()
		if self.db.profile.autogroups then
			local size = self:GetInstanceSize()
			return groups[size]
		else
			return self.db.profile.groups
		end
	end
end

do -- BigBrother:GetChatChannels()
	local channels = {}
	local function updateChannels()
		wipe(channels)
		for i = 1, GetNumDisplayChannels() do
			local name, _, _, _, _, _, category = GetChannelDisplayInfo(i)
			if category == "CHANNEL_CATEGORY_CUSTOM" then
				channels[name] = name
			end
		end
	end

	function BigBrother:GetChatChannels()
		return channels
	end

	function BigBrother:CHANNEL_UI_UPDATE()
		updateChannels()
		LibStub("AceConfigRegistry-3.0"):NotifyChange("BigBrother")
	end
end

do -- BigBrother:IterateGroup()
	local partyUnits = {"player", "party1", "party2", "party3", "party4"}

	local raidUnits = {}
	for i = 1, MAX_RAID_MEMBERS do
		raidUnits[#raidUnits + 1] = ("raid%d"):format(i)
	end

	function BigBrother:IterateGroup()
		local i = 0
		local size = GetNumGroupMembers()
		if size == 0 then size = 1 end

		local function iter(a)
			i = i + 1
			if i <= size then
				return a[i], i
			end
		end

		return iter, (IsInRaid() and raidUnits or partyUnits)
	end
end

function BigBrother:UnitName(unit)
	local name, server = UnitName(unit)
	if server and server ~= "" then
		name = name.."-"..server
	end
	return name
end

function BigBrother:OpenOptions()
	InterfaceOptionsFrame_OpenToCategory("BigBrother")
	InterfaceOptionsFrame_OpenToCategory("BigBrother")
end

SlashCmdList.BIGBROTHER = function(input)
	local command, arg = string.match(input, "^(%S*)%s*(.-)$")
	command = command and command:lower()
	if command == "check" or command == "qc" then
		local arg = (arg and arg ~= "") and arg:trim():lower() or nil
		if arg == "raidwarning" then arg = "raid_warning" end
		BigBrother:BuffCheck(arg)
	elseif command == "window" or command == "bc" then
		BigBrother:ToggleBuffWindow()
	elseif command == "config" then
		BigBrother:OpenOptions()
	else
		BigBrother:Print("|cffffff7f/bb check [self||say||group||party||raid||raidwarning||guild||officer]|r: " .. L["Report who is missing consumables and/or buffs."])
		BigBrother:Print("|cffffff7f/bb window|r: " .. L["Opens the buff window (drag the bottom to resize)."])
		BigBrother:Print("|cffffff7f/bb config|r: " .. L["Open settings."])
	end
end
SLASH_BIGBROTHER1 = "/bigbrother"
SLASH_BIGBROTHER2 = "/bb"
