--[[--------------------------------------------------------------------
	* Plugins pass their info using the table like:
	addon = {
		Title = "Your Own Title",
		Name = "AddOnName",
		tutorialImage = "TexturePath",
		tutorialImageSize = {x,y},
		tutorialImagetutorialImagePoint = {xOffset,yOffset},
		Pages = {
			function1,
			function2,
			function3,
		},
		StepTitles = {
			"Title 1",
			"Title 2",
			"Title 3",
		},
		StepTitlesColor = {r, g, b},
		StepTitlesColorSelected = {r, g, b},
		StepTitleWidth = 140,
		StepTitleButtonWidth = 130,
		StepTitleTextJustification = "CENTER"
	}

	E:GetModule("PluginInstaller"):Queue(addon)

	* Title is wat displayed on top of the window. By default it's "ElvUI Plugin Installation"
	* Name is how your installation will be showin in "pending list", Default is "Unknown"
	* tutorialImage is a path to your own texture to use in frame. if not specified, then it will use ElvUI's one
	* Pages is a table to set up pages of your install where numbers are representing actual pages" order and function is what previously was used to set layout. For example

	function function1()
		PluginInstallFrame.SubTitle:SetText("Title Text")
		PluginInstallFrame.Desc1:SetText("Desc 1 Tet")
		PluginInstallFrame.Desc2:SetText("Desc 2 Tet")
		PluginInstallFrame.Desc3:SetText("Desc 3 Tet")

		PluginInstallFrame.Option1:Show()
		PluginInstallFrame.Option1:SetScript("OnClick", function() <Do Some Stuff> end)
		PluginInstallFrame.Option1:SetText("Text 1")

		PluginInstallFrame.Option2:Show()
		PluginInstallFrame.Option2:SetScript("OnClick", function() <Do Some Other Stuff> end)
		PluginInstallFrame.Option2:SetText("Text 2")
	end

	StepTitles					- a table to specify "titles" for your install steps.
		* If specified and number of lines here = number of pages then you"ll get an additional frame to the right of main frame
		* with a list of steps (current one being highlighted), clicking on those will open respective step. BenikUI style of doing stuff.
	StepTitlesColor				- a table with color values to color "titles" when they are not active
	StepTitlesColorSelected		- a table with color values to color "titles" when they are active
	StepTitleWidth				- Width of the steps frame on the right side
	StepTitleButtonWidth		- Width of each step button in the steps frame
	StepTitleTextJustification	- The justification of the text on each step button ("LEFT", "RIGHT", "CENTER"). Default: "CENTER"
--------------------------------------------------------------------]]--

local E, L, V, P, G = unpack(ElvUI)
local PI = E:GetModule("PluginInstaller")
local S = E:GetModule("Skins")

local pairs, unpack = pairs, unpack
local tinsert, tremove, format = tinsert, tremove, format

local PlaySound = PlaySound
local CreateFrame = CreateFrame
local UIFrameFadeOut = UIFrameFadeOut
local CONTINUE, PREVIOUS, UNKNOWN = CONTINUE, PREVIOUS, UNKNOWN
-- GLOBALS: PluginInstallFrame

--Installation Functions
PI.Installs = {}
local BUTTON_HEIGHT = 20
local f

local titleColor = {1, 1, 1}
local titleSelectedColor = {.09, .52, .82}

function PI:SetupReset()
	f.Next:Disable()
	f.Prev:Disable()
	f.Option1:Hide()
	f.Option1:SetScript("OnClick", nil)
	f.Option1:SetText("")
	f.Option1:ClearAllPoints()
	f.Option1:Point("BOTTOM", 0, 45)
	f.Option2:Hide()
	f.Option2:SetScript("OnClick", nil)
	f.Option2:SetText("")
	f.Option2:ClearAllPoints()
	f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45)
	f.Option3:Hide()
	f.Option3:SetScript("OnClick", nil)
	f.Option3:SetText("")
	f.Option3:ClearAllPoints()
	f.Option3:Point("LEFT", f.Option2, "RIGHT", 4, 0)
	f.Option4:Hide()
	f.Option4:SetScript("OnClick", nil)
	f.Option4:SetText("")
	f.Option4:ClearAllPoints()
	f.Option4:Point("LEFT", f.Option3, "RIGHT", 4, 0)
	f.SubTitle:SetText("")
	f.Desc1:SetText("")
	f.Desc2:SetText("")
	f.Desc3:SetText("")
	f.Desc4:SetText("")

	f:Size(550, 400)

	if f.StepTitles then
		for i = 1, #f.side.Lines do
			f.side.Lines[i].text:SetText("")
		end
	end
end

function PI:SetPage(PageNum, PrevPage)
	PI:SetupReset()

	f.Status.anim.progress:SetChange(PageNum)
	f.Status.anim.progress:Play()
	f.CurrentPage = PageNum
	f.PrevPage = PrevPage

	local r, g, b = E:ColorGradient(f.CurrentPage / f.MaxPage, 1, 0, 0, 1, 1, 0, 0, 1, 0)
	f.Status:SetStatusBarColor(r, g, b)

	f.Next:SetEnabled(PageNum ~= f.MaxPage)
	f.Prev:SetEnabled(PageNum ~= 1)

	f.Pages[f.CurrentPage]()
	f.Status.text:SetFormattedText("%d / %d", f.CurrentPage, f.MaxPage)

	if f.StepTitles then
		for i = 1, #f.side.Lines do
			local line, color = f.side.Lines[i]
			if i == f.CurrentPage then
				color = f.StepTitlesColorSelected or {.09,.52,.82}
			else
				color = f.StepTitlesColor or {1,1,1}
			end

			line.text:SetText(f.StepTitles[i])
			line.text:SetTextColor(color[1] or color.r, color[2] or color.g, color[3] or color.b)
		end
	end
end

function PI:NextPage()
	if f.CurrentPage ~= f.MaxPage then
		f.CurrentPage = f.CurrentPage + 1
		PI:SetPage(f.CurrentPage, f.CurrentPage - 1)
	end
end

function PI:PreviousPage()
	if f.CurrentPage ~= 1 then
		f.CurrentPage = f.CurrentPage - 1
		PI:SetPage(f.CurrentPage, f.CurrentPage + 1)
	end
end

function PI:CreateStepComplete()
	local imsg = CreateFrame("Frame", "PluginInstallStepComplete", E.UIParent)
	imsg:Size(418, 72)
	imsg:Point("TOP", 0, -190)
	imsg:Hide()
	imsg:SetScript("OnShow", function(frame)
		if frame.message then
			PlaySound(888) -- LEVELUP
			frame.text:SetText(frame.message)
			UIFrameFadeOut(frame, 3.5, 1, 0)
			E:Delay(4, frame.Hide, frame)
			frame.message = nil
		else
			frame:Hide()
		end
	end)

	imsg.firstShow = false

	imsg.bg = imsg:CreateTexture(nil, "BACKGROUND")
	imsg.bg:SetTexture([[Interface\AddOns\ElvUI\media\textures\LevelUpTex]])
	imsg.bg:Point("BOTTOM")
	imsg.bg:Size(326, 103)
	imsg.bg:SetTexCoord(0.00195313, 0.63867188, 0.03710938, 0.23828125)
	imsg.bg:SetVertexColor(1, 1, 1, 0.6)

	imsg.lineTop = imsg:CreateTexture(nil, "BACKGROUND")
	imsg.lineTop:SetDrawLayer("BACKGROUND", 2)
	imsg.lineTop:SetTexture([[Interface\AddOns\ElvUI\media\textures\LevelUpTex]])
	imsg.lineTop:Point("TOP")
	imsg.lineTop:Size(418, 7)
	imsg.lineTop:SetTexCoord(0.00195313, 0.81835938, 0.01953125, 0.03320313)

	imsg.lineBottom = imsg:CreateTexture(nil, "BACKGROUND")
	imsg.lineBottom:SetDrawLayer("BACKGROUND", 2)
	imsg.lineBottom:SetTexture([[Interface\AddOns\ElvUI\media\textures\LevelUpTex]])
	imsg.lineBottom:Point("BOTTOM")
	imsg.lineBottom:Size(418, 7)
	imsg.lineBottom:SetTexCoord(0.00195313, 0.81835938, 0.01953125, 0.03320313)

	imsg.text = imsg:CreateFontString(nil, "ARTWORK")
	imsg.text:FontTemplate(E.media.normFont, 32, "OUTLINE")
	imsg.text:Point("BOTTOM", 0, 12)
	imsg.text:SetTextColor(1, 0.82, 0)
	imsg.text:SetJustifyH("CENTER")
end

function PI:Button_OnClick()
	local id = self:GetID()
	if id and id <= f.MaxPage then
		PI:SetPage(id, f.CurrentPage)
	end
end

function PI:Pending_OnEnter()
	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMLEFT", E.PixelMode and -7 or -9)
	GameTooltip:AddLine(L["List of installations in queue:"], 1, 1, 1)
	GameTooltip:AddLine(" ")
	for i = 1, #PI.Installs do
		GameTooltip:AddDoubleLine(format("%d. %s", i, (PI.Installs[i].Name or UNKNOWN)), i == 1 and format("|cff00FF00%s|r", L["In Progress"]) or format("|cffFF0000%s|r", L["Pending"]))
	end
	GameTooltip:Show()
end

function PI:Pending_OnLeave()
	GameTooltip:Hide()
end

function PI:Frame_OnShow()
	if f.CurrentPage == 0 then
		PI:NextPage()
	else
		f.Pages[f.CurrentPage]()
	end
end

function PI:Frame_OnHide() end -- for plugins

function PI:CreateFrame()
	f = CreateFrame("Button", "PluginInstallFrame", E.UIParent)
	f:Size(550, 400)
	f:SetMovable(true)
	f:SetFrameStrata("TOOLTIP")
	f:SetScript("OnShow", PI.Frame_OnShow)
	f:SetScript("OnHide", PI.Frame_OnHide)
	f:SetTemplate("Transparent")
	f:Point("CENTER")

	f.MoveFrame = CreateFrame("Frame", nil, f)
	f.MoveFrame:SetMovable(true)
	f.MoveFrame:EnableMouse(true)
	f.MoveFrame:RegisterForDrag("LeftButton")
	f.MoveFrame:SetScript("OnDragStart", function(frame) frame:StartMoving() frame:SetUserPlaced(false) end)
	f.MoveFrame:SetScript("OnDragStop", function(frame) frame:StopMovingOrSizing() end)
	f.MoveFrame:Size(450, 50)
	f.MoveFrame:Point("TOP", f, "TOP")

	f.Title = f:CreateFontString(nil, "OVERLAY")
	f.Title:FontTemplate(nil, 17, nil)
	f.Title:Point("TOP", 0, -5)

	f.Next = CreateFrame("Button", "PluginInstallNextButton", f, "UIPanelButtonTemplate")
	f.Next:Size(110, 25)
	f.Next:Point("BOTTOMRIGHT", -5, 5)
	f.Next:SetText(CONTINUE)
	f.Next:Disable()
	f.Next:SetScript("OnClick", PI.NextPage)
	S:HandleButton(f.Next)

	f.Prev = CreateFrame("Button", "PluginInstallPrevButton", f, "UIPanelButtonTemplate")
	f.Prev:Size(110, 25)
	f.Prev:Point("BOTTOMLEFT", 5, 5)
	f.Prev:SetText(PREVIOUS)
	f.Prev:Disable()
	f.Prev:SetScript("OnClick", PI.PreviousPage)
	S:HandleButton(f.Prev)

	f.Status = CreateFrame("StatusBar", "PluginInstallStatus", f)
	f.Status:OffsetFrameLevel(2)
	f.Status:CreateBackdrop(nil, true)
	f.Status:SetStatusBarTexture(E.media.normTex)
	f.Status:SetStatusBarColor(unpack(E.media.rgbvaluecolor))
	f.Status:Point("TOPLEFT", f.Prev, "TOPRIGHT", 6, -2)
	f.Status:Point("BOTTOMRIGHT", f.Next, "BOTTOMLEFT", -6, 2)
	-- Setup StatusBar Animation
	f.Status.anim = CreateAnimationGroup(f.Status)
	f.Status.anim.progress = f.Status.anim:CreateAnimation("Progress")
	f.Status.anim.progress:SetEasing("Out")
	f.Status.anim.progress:SetDuration(.3)

	f.Status.text = f.Status:CreateFontString(nil, "OVERLAY")
	f.Status.text:FontTemplate(nil, 14, "OUTLINE")
	f.Status.text:Point("CENTER")

	f.Option1 = CreateFrame("Button", "PluginInstallOption1Button", f, "UIPanelButtonTemplate")
	f.Option1:Size(160, 30)
	f.Option1:Point("BOTTOM", 0, 45)
	f.Option1:SetText("")
	f.Option1:Hide()
	S:HandleButton(f.Option1)

	f.Option2 = CreateFrame("Button", "PluginInstallOption2Button", f, "UIPanelButtonTemplate")
	f.Option2:Size(110, 30)
	f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45)
	f.Option2:SetText("")
	f.Option2:Hide()
	f.Option2:SetScript("OnShow", function() f.Option1:Width(110); f.Option1:ClearAllPoints(); f.Option1:Point("BOTTOMRIGHT", f, "BOTTOM", -4, 45) end)
	f.Option2:SetScript("OnHide", function() f.Option1:Width(160); f.Option1:ClearAllPoints(); f.Option1:Point("BOTTOM", 0, 45) end)
	S:HandleButton(f.Option2)

	f.Option3 = CreateFrame("Button", "PluginInstallOption3Button", f, "UIPanelButtonTemplate")
	f.Option3:Size(100, 30)
	f.Option3:Point("LEFT", f.Option2, "RIGHT", 4, 0)
	f.Option3:SetText("")
	f.Option3:Hide()
	f.Option3:SetScript("OnShow", function() f.Option1:SetWidth(100) f.Option1:ClearAllPoints() f.Option1:Point("RIGHT", f.Option2, "LEFT", -4, 0) f.Option2:SetWidth(100) f.Option2:ClearAllPoints() f.Option2:Point("BOTTOM", f, "BOTTOM", 0, 45) end)
	f.Option3:SetScript("OnHide", function() f.Option1:SetWidth(160) f.Option1:ClearAllPoints() f.Option1:Point("BOTTOM", 0, 45) f.Option2:SetWidth(110) f.Option2:ClearAllPoints() f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45) end)
	S:HandleButton(f.Option3, true)

	f.Option4 = CreateFrame("Button", "PluginInstallOption4Button", f, "UIPanelButtonTemplate")
	f.Option4:Size(100, 30)
	f.Option4:Point("LEFT", f.Option3, "RIGHT", 4, 0)
	f.Option4:SetText("")
	f.Option4:Hide()
	f.Option4:SetScript("OnShow", function()
		f.Option1:Width(100)
		f.Option2:Width(100)

		f.Option1:ClearAllPoints()
		f.Option1:Point("RIGHT", f.Option2, "LEFT", -4, 0)
		f.Option2:ClearAllPoints()
		f.Option2:Point("BOTTOMRIGHT", f, "BOTTOM", -4, 45)
	end)
	f.Option4:SetScript("OnHide", function() f.Option1:Width(160); f.Option1:ClearAllPoints(); f.Option1:Point("BOTTOM", 0, 45); f.Option2:Width(110); f.Option2:ClearAllPoints(); f.Option2:Point("BOTTOMLEFT", f, "BOTTOM", 4, 45) end)
	S:HandleButton(f.Option4)

	f.SubTitle = f:CreateFontString(nil, "OVERLAY")
	f.SubTitle:FontTemplate(nil, 15, nil)
	f.SubTitle:Point("TOP", 0, -40)

	f.Desc1 = f:CreateFontString(nil, "OVERLAY")
	f.Desc1:FontTemplate()
	f.Desc1:Point("TOPLEFT", 20, -75)
	f.Desc1:Width(f:GetWidth() - 40)

	f.Desc2 = f:CreateFontString(nil, "OVERLAY")
	f.Desc2:FontTemplate()
	f.Desc2:Point("TOP", f.Desc1, "BOTTOM", 0, -20)
	f.Desc2:Width(f:GetWidth() - 40)

	f.Desc3 = f:CreateFontString(nil, "OVERLAY")
	f.Desc3:FontTemplate()
	f.Desc3:Point("TOP", f.Desc2, "BOTTOM", 0, -20)
	f.Desc3:Width(f:GetWidth() - 40)

	f.Desc4 = f:CreateFontString(nil, "OVERLAY")
	f.Desc4:FontTemplate()
	f.Desc4:Point("TOP", f.Desc3, "BOTTOM", 0, -20)
	f.Desc4:Width(f:GetWidth() - 40)

	local close = CreateFrame("Button", "PluginInstallCloseButton", f, "UIPanelCloseButton")
	close:Point("TOPRIGHT", f, "TOPRIGHT")
	close:SetScript("OnClick", PI.CloseInstall)
	S:HandleCloseButton(close)

	f.pending = CreateFrame("Frame", "PluginInstallPendingButton", f)
	f.pending:Size(20, 20)
	f.pending:Point("TOPLEFT", f, "TOPLEFT", 8, -8)
	f.pending.tex = f.pending:CreateTexture(nil, "OVERLAY")
	f.pending.tex:Point("TOPLEFT", f.pending, "TOPLEFT", 2, -2)
	f.pending.tex:Point("BOTTOMRIGHT", f.pending, "BOTTOMRIGHT", -2, 2)
	f.pending.tex:SetTexture([[Interface\OptionsFrame\UI-OptionsFrame-NewFeatureIcon]])
	f.pending:CreateBackdrop("Transparent")
	f.pending:SetScript("OnEnter", PI.Pending_OnEnter)
	f.pending:SetScript("OnLeave", PI.Pending_OnLeave)

	f.tutorialImage = f:CreateTexture("PluginInstallTutorialImage", "OVERLAY")
	f.tutorialImage2 = f:CreateTexture("PluginInstallTutorialImage2", "OVERLAY")

	f.side = CreateFrame("Frame", "PluginInstallTitleFrame", f)
	f.side:SetTemplate("Transparent")
	f.side:Point("TOPLEFT", f, "TOPRIGHT", E.PixelMode and 1 or 3, 0)
	f.side:Point("BOTTOMLEFT", f, "BOTTOMRIGHT", E.PixelMode and 1 or 3, 0)
	f.side:Width(140)
	f.side.text = f.side:CreateFontString(nil, "OVERLAY")
	f.side.text:Point("TOP", f.side, "TOP", 0, -4)
	f.side.text:FontTemplate(nil, 18, "OUTLINE")
	f.side.text:SetText(L["Steps"])
	f.side.Lines = {} --Table to keep shown lines
	f.side:Hide()

	for i = 1, 18 do
		local button = CreateFrame("Button", nil, f)
		if i == 1 then
			button:Point("TOP", f.side.text, "BOTTOM", 0, -6)
		else
			button:Point("TOP", f.side.Lines[i - 1], "BOTTOM")
		end

		button.text = button:CreateFontString(nil, "OVERLAY")
		button.text:Point("TOPLEFT", button, "TOPLEFT", 2, -2)
		button.text:Point("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 2)
		button.text:FontTemplate(nil, 14, "OUTLINE")
		button.text:SetText("")

		button:SetScript("OnClick", PI.Button_OnClick)
		button:Size(130, BUTTON_HEIGHT)
		button:SetID(i)
		button:Hide()

		f.side.Lines[i] = button
	end

	f:Hide()
end

function PI:Queue(addon)
	local addonIsQueued = false
	for _, v in pairs(PI.Installs) do
		if v.Name == addon.Name then
			addonIsQueued = true
		end
	end

	if not addonIsQueued then
		tinsert(PI.Installs, #(PI.Installs)+1, addon)
		PI:RunInstall()
	end
end

function PI:CloseInstall()
	tremove(PI.Installs, 1)

	f:Hide()
	f.side:Hide()

	for i = 1, #f.side.Lines do
		local line = f.side.Lines[i]
		line.text:SetText("")
		line:Hide()
	end

	if #PI.Installs > 0 then
		E:Delay(1, PI.RunInstall, PI)
	end
end

function PI:RunInstall()
	if not E.private.install_complete then return end

	local db = PI.Installs[1]
	if db and not f:IsShown() and not (E.InstallFrame and E.InstallFrame:IsShown()) then
		f.StepTitles = nil
		f.StepTitlesColor = nil
		f.StepTitlesColorSelected = nil

		f.Pages = db.Pages
		f.MaxPage = #f.Pages
		f.CurrentPage = 0

		f.Title:SetText(db.Title or L["ElvUI Plugin Installation"])
		f.Status:SetMinMaxValues(0, f.MaxPage)
		f.Status.text:SetText(f.CurrentPage.." / "..f.MaxPage)

		-- Logo
		local LogoTop = db.tutorialImage or E.Media.Textures.LogoTop
		f.tutorialImage:SetTexture(LogoTop)
		f.tutorialImage:ClearAllPoints()
		if db.tutorialImageSize then
			f.tutorialImage:Size(db.tutorialImageSize[1], db.tutorialImageSize[2])
		else
			f.tutorialImage:Size(256, 128)
		end
		if db.tutorialImagePoint then
			f.tutorialImage:Point("BOTTOM", 0 + db.tutorialImagePoint[1], 70 + db.tutorialImagePoint[2])
		else
			f.tutorialImage:Point("BOTTOM", 0, 70)
		end
		if db.tutorialImageVertexColor then
			f.tutorialImage:SetVertexColor(unpack(db.tutorialImageVertexColor))
		elseif LogoTop == E.Media.Textures.LogoTop then
			f.tutorialImage:SetVertexColor(unpack(E.media.rgbvaluecolor))
		else
			f.tutorialImage:SetVertexColor(1, 1, 1)
		end

		--Alt Logo
		if LogoTop == E.Media.Textures.LogoTop or db.tutorialImage2 then
			f.tutorialImage2:SetTexture(db.tutorialImage2 or E.Media.Textures.LogoBottom)
			f.tutorialImage2:ClearAllPoints()
			if db.tutorialImage2Size then
				f.tutorialImage2:Size(db.tutorialImage2Size[1], db.tutorialImage2Size[2])
			else
				f.tutorialImage2:Size(256, 128)
			end
			if db.tutorialImage2Point then
				f.tutorialImage2:Point("BOTTOM", 0 + db.tutorialImage2Point[1], 70 + db.tutorialImage2Point[2])
			else
				f.tutorialImage2:Point("BOTTOM", 0, 70)
			end
			if db.tutorialImage2VertexColor then
				f.tutorialImage2:SetVertexColor(unpack(db.tutorialImage2VertexColor))
			else
				f.tutorialImage2:SetVertexColor(1, 1, 1)
			end
		end

		if db.StepTitles and #db.StepTitles == f.MaxPage then
			f:Point("CENTER", E.UIParent, "CENTER", -((db.StepTitleWidth or 140)*0.5), 0)
			f.side:Width(db.StepTitleWidth or 140)
			f.side:Show()

			for i = 1, #f.side.Lines do
				if db.StepTitles[i] then
					local line = f.side.Lines[i]
					line.text:SetJustifyH(db.StepTitleTextJustification or "CENTER")
					line:Width(db.StepTitleButtonWidth or 130)
					line:Show()
				end
			end

			f.StepTitles = db.StepTitles
			f.StepTitlesColor = db.StepTitlesColor
			f.StepTitlesColorSelected = db.StepTitlesColorSelected
		end

		f:ClearAllPoints()
		f:Point("CENTER")
		f:Show()
	end

	if #PI.Installs > 1 then
		f.pending:Show()
		E:Flash(f.pending, 0.53, true)
	else
		f.pending:Hide()
		E:StopFlash(f.pending)
	end
end

function PI:Initialize()
	PI.Initialized = true
	PI:CreateStepComplete()
	PI:CreateFrame()
end

E:RegisterModule(PI:GetName())