--[[--------------------------------------------------------------------
	* Plugins pass their info using the table like:
	addon = {
		Title = 'Your Own Title',
		Name = 'AddOnName',
		tutorialImage = 'TexturePath',
		tutorialImageSize = {x,y},
		tutorialImagePoint = {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 _G = _G
local pairs, unpack, type = pairs, unpack, type
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 titleSelectedColor
			else
				color = f.StepTitlesColor or titleColor
			end

			local StepTitleText
			if type(f.StepTitles[i]) == 'function' then
				StepTitleText = f.StepTitles[i]()
			else
				StepTitleText = f.StepTitles[i]
			end

			line.text:SetText(StepTitleText)
			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 Sound
			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\LevelUp\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\LevelUp\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\LevelUp\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', 'GameFont_Gigantic')
	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()
	_G.GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMLEFT', E.PixelMode and -7 or -9)
	_G.GameTooltip:AddLine(L["List of installations in queue:"], 1, 1, 1)
	_G.GameTooltip:AddLine(' ')
	for i = 1, #PI.Installs do
		_G.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
	_G.GameTooltip:Show()
end

function PI:Pending_OnLeave()
	_G.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, 'TitleDragAreaTemplate')
	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 = _G.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:Width(100); f.Option1:ClearAllPoints(); f.Option1:Point('RIGHT', f.Option2, 'LEFT', -4, 0); f.Option2:Width(100); f.Option2:ClearAllPoints(); f.Option2:Point('BOTTOM', f, 'BOTTOM', 0, 45) end)
	f.Option3: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.Option3)

	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)
	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:ClearAllPoints()
			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.5, true)
	else
		f.pending:Hide()
		E:StopFlash(f.pending, 1)
	end
end

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

E:RegisterModule(PI:GetName())
