local _, GF = ...

GF.CreateDrawer = {}
local CD = GF.CreateDrawer

local PANEL_W = GF.CREATE_DRAWER_W or GF.SIDE_PANEL_W or 260
local PANEL_GAP = GF.SATELLITE_PANEL_GAP or 2

local function filterFooterAtlasTopOffset()
	local offset = GF.FILTER_FOOTER_ATLAS_TOP_OFFSET
	if offset == nil then
		offset = GF.BROWSE_CONTROL_BACKGROUND_OFFSET_Y or 0
	end
	return offset or 0
end

local function applyDrawerTitleStyle(frame)
	local title = frame and frame.titletext
	if not title then
		return
	end
	title._gfFontSizeOverride = 14
	if GF.Font and GF.Font.ApplyToFontString then
		GF.Font.ApplyToFontString(title, title._gfFontTemplate or "GameFontNormal")
	end
end

local function isFrameResizing()
	if GF._frameResizing then
		return true
	end
	local cp = GF.CreatePanel
	return cp and cp._frameResizing
end

local function isMainFrameShown()
	local frame = GF.MainFrame and GF.MainFrame.frame
	return frame and frame.IsShown and frame:IsShown()
end

function CD:Init(content, contentBody)
	if self.frame then
		return
	end
	self.content = content
	self.host = contentBody or content
	self.mainFrame = GF.MainFrame and GF.MainFrame.frame
	self.open = false
	self._tabActive = false
	self._userClosedCreate = false

	local L = GF.L or {}
	self.frame = CreateFrame("Frame", "GroupFinderAddonCreateListingFrame", UIParent, "SettingsFrameTemplate")
	self.frame:SetSize(PANEL_W, self.mainFrame and self.mainFrame:GetHeight() or 520)
	self.frame:EnableMouse(true)
	self.frame:SetClampedToScreen(true)
	self.frame:Hide()
	self.frame:HookScript("OnMouseDown", function()
		if GF.CreatePanel and GF.CreatePanel.ActivateCreateChannel then
			GF.CreatePanel:ActivateCreateChannel()
		elseif GF.BlizzardBorrow and GF.BlizzardBorrow.SetActiveOwner then
			GF.BlizzardBorrow.SetActiveOwner("groupfinder")
		end
	end)
	GF.UI.InstallSatelliteFrame(self.frame, { levelOffset = 0, raise = false, toplevel = false })
	GF.UI.ApplySettingsFrameChrome(self.frame, L.TAB_CREATE or "Create Listing")
	applyDrawerTitleStyle(self.frame)
	GF.UI.InstallBodyBackground(self.frame, { layout = "filter", style = "panelBackplate" })
	if self.frame.ClosePanelButton then
		self.frame.ClosePanelButton:SetScript("OnClick", function()
			CD:Close()
		end)
	end
	self.frame:HookScript("OnHide", function()
		if CD.open and not CD._closing then
			CD:Close()
		end
	end)

	local contentLevel = self.frame:GetFrameLevel() + 5
	local footerH = GF.FILTER_FOOTER_H or GF.SUBTITLE_H or 42
	local footerInsetL = GF.FILTER_FOOTER_INSET_L or GF.FRAME_BG_INSET_LEFT or 7
	local footerInsetR = GF.FILTER_FOOTER_INSET_R or GF.FRAME_BG_INSET_RIGHT or -2
	local footerInsetB = GF.FILTER_FOOTER_INSET_B or GF.FRAME_BG_INSET_BOTTOM or 3
	self.footer = CreateFrame("Frame", nil, self.frame)
	self.footer:SetPoint("BOTTOMLEFT", self.frame, "BOTTOMLEFT", footerInsetL, footerInsetB)
	self.footer:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT", footerInsetR, footerInsetB)
	self.footer:SetHeight(footerH)
	self.footer:SetFrameLevel(contentLevel)
	if GF.UI.InstallBrowseControlBarChrome then
		GF.UI.InstallBrowseControlBarChrome(self.footer, {
			backgroundParent = self.footer,
			leftInset = 0,
			rightInset = 0,
			height = GF.BROWSE_CONTROL_BACKGROUND_H or GF.SUBTITLE_HEADER_H or 26,
			topOffset = GF.BROWSE_CONTROL_BACKGROUND_OFFSET_Y or 0,
		})
	end

	self.panelHost = CreateFrame("Frame", nil, self.frame)
	self.panelHost:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 4, -28)
	self.panelHost:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT", 0, footerH + footerInsetB + filterFooterAtlasTopOffset())
	self.panelHost:SetFrameLevel(contentLevel)
	self.panelHost._gfCreateDrawerFooter = self.footer
	self.panelHost:EnableMouse(true)
	self.panelHost:HookScript("OnMouseDown", function()
		if GF.CreatePanel and GF.CreatePanel.ActivateCreateChannel then
			GF.CreatePanel:ActivateCreateChannel()
		end
	end)

	local function requestLayout()
		CD:Layout()
	end
	if self.mainFrame then
		self.mainFrame:HookScript("OnSizeChanged", requestLayout)
	end
	if content and content.HookScript then
		content:HookScript("OnSizeChanged", requestLayout)
	end
	if UISpecialFrames and self.frame.GetName and self.frame:GetName() then
		tinsert(UISpecialFrames, self.frame:GetName())
	end
end

function CD:IsOpen()
	return self.open == true and self.frame and self.frame:IsShown()
end

function CD:AnchorToMain()
	if not self.frame then
		return
	end
	local mainFrame = self.mainFrame or (GF.MainFrame and GF.MainFrame.frame)
	if not mainFrame then
		return
	end
	self.mainFrame = mainFrame
	self.frame:SetWidth(PANEL_W)
	self.frame:SetHeight(mainFrame:GetHeight())
	self.frame:ClearAllPoints()
	self.frame:SetPoint("TOPLEFT", mainFrame, "TOPRIGHT", PANEL_GAP, 0)
	self.frame:SetPoint("BOTTOMLEFT", mainFrame, "BOTTOMRIGHT", PANEL_GAP, 0)
end

function CD:SyncActivityTitle()
	if not self.frame then
		return
	end
	local L = GF.L or {}
	local text = ""
	if GF.Listing and GF.Listing.GetActiveActivityTitle then
		text = GF.Listing:GetActiveActivityTitle() or ""
	end
	if text == "" and GF.CreatePanel and GF.CreatePanel.selection then
		local node = GF.CreatePanel.selection
		if node.activityID then
			local info = node.activityInfo or C_LFGList.GetActivityInfoTable(node.activityID)
			text = GF.UI.GetCategoryTitle(node.categoryID, info)
		else
			text = node.label or ""
		end
	end
	if text == "" then
		text = L.TAB_CREATE or "Create Listing"
	end
	GF.UI.ApplySettingsFrameChrome(self.frame, text)
	applyDrawerTitleStyle(self.frame)
end

function CD:Layout()
	if not self.frame then
		return
	end
	self:AnchorToMain()
	if not self.open or not GF.CreatePanel then
		return
	end
	if isFrameResizing() then
		return
	end
	if GF.CreatePanel.ScheduleUpdateScrollLayout then
		GF.CreatePanel:ScheduleUpdateScrollLayout()
	elseif GF.CreatePanel.UpdateScrollLayout then
		GF.CreatePanel:UpdateScrollLayout()
	end
end

function CD:SetTabActive(active)
	self._tabActive = active and isMainFrameShown() and true or false
	if not self._tabActive then
		self:Close(true)
		self._userClosedCreate = false
		return
	end
	self:Layout()
end

function CD:SyncDefaultState(hasActive, opts)
	if not self._tabActive or not isMainFrameShown() then
		return
	end
	opts = opts or {}
	if hasActive then
		if GF.Listing and GF.Listing.IsActiveEntryGroupFinderOwned then
			self._lastActiveListingWasGroupFinder = GF.Listing:IsActiveEntryGroupFinderOwned() == true
		end
		self._userClosedCreate = false
		local canManage = GF.Listing and GF.Listing.CanManageEntry and GF.Listing:CanManageEntry()
		if not canManage then
			self:Open({ mode = "edit", silent = true })
			return
		end
		if not self.open and GF.CreatePanel then
			GF.CreatePanel:Hide()
		end
		return
	end
	if self._lastActiveListingWasGroupFinder == false then
		self._lastActiveListingWasGroupFinder = nil
		self:Close(true)
		return
	end
	self._lastActiveListingWasGroupFinder = nil
	if GF.Listing and GF.Listing.CanLeadListing and not GF.Listing:CanLeadListing() then
		self:Close(true)
		return
	end
	if not opts.allowOccupiedPrompt and GF.CreatePanel and GF.CreatePanel.IsCreateChannelAutoOpenBlocked and GF.CreatePanel:IsCreateChannelAutoOpenBlocked() then
		self:Close(true)
		return
	end
	if self._userClosedCreate then
		return
	end
	self:Open({ mode = "create", silent = true })
end

function CD:Open(opts)
	opts = opts or {}
	if not self._tabActive or not isMainFrameShown() then
		return
	end
	if GF.CreatePanel and GF.CreatePanel.ActivateCreateChannel then
		GF.CreatePanel:ActivateCreateChannel()
	elseif GF.BlizzardBorrow and GF.BlizzardBorrow.SetActiveOwner then
		GF.BlizzardBorrow.SetActiveOwner("groupfinder")
	end
	if opts.mode == "edit" and (not GF.Listing or not GF.Listing:HasActive()) then
		return
	end
	local wasShown = self.frame and self.frame:IsShown()
	self.open = true
	self._userClosedCreate = false
	self:Layout()
	if GF.CreatePanel then
		if opts.mode == "create" then
			GF.CreatePanel:PrepareForCreate()
		elseif opts.mode == "edit" or (GF.Listing and GF.Listing:HasActive()) then
			GF.CreatePanel:PrepareForEdit()
		else
			GF.CreatePanel:PrepareForCreate()
		end
		GF.CreatePanel:Show()
	end
	self:SyncActivityTitle()
	if self.frame then
		if GF.UI and GF.UI.ApplyBodyBackground then
			GF.UI.ApplyBodyBackground(self.frame)
		end
		self.frame:Show()
	end
	self:Layout()
	if not wasShown and not opts.silent and GF.UI and GF.UI.PlayUISound then
		GF.UI.PlayUISound("open")
	end
end

function CD:Close(force)
	if not self._tabActive and not force then
		return
	end
	local wasShown = self.frame and self.frame:IsShown()
	local wasCreateMode = GF.CreatePanel and GF.CreatePanel.editMode ~= true
	self.open = false
	if force then
		self._userClosedCreate = false
	elseif wasCreateMode then
		self._userClosedCreate = true
	end
	if GF.CreatePanel then
		GF.CreatePanel:ClearFocus()
		GF.CreatePanel:ReleaseCreateFields("panel")
		GF.CreatePanel:Hide()
	end
	if self.frame then
		self._closing = true
		self.frame:Hide()
		self._closing = nil
	end
	if wasShown and not force and GF.UI and GF.UI.PlayUISound then
		GF.UI.PlayUISound("close")
	end
end

function CD:Toggle()
	if self:IsOpen() then
		self:Close()
	else
		self:Open()
	end
end
