-------------------------------------------------
-- Tech Tree Popup
-- updated by psparky for VP - requires EUI 1.28g, as used with VP (changes marked afw)
-- coded by bc1 from Civ V 1.0.3.276 code
-- capture choose tech & steal tech popup events
-- fix escape/enter popup exit code
-- support Technology_ORPrereqTechs in addition to Technology_PrereqTechs
-- code is common except for vanila gk_mode needs to be set false
-- decreased code size by over 1/3 and still do more :lol:
-------------------------------------------------
Events.SequenceGameInitComplete.Add(function()
-- print("Loading EUI tech tree",ContextPtr,os.clock(),[[
print("Loading Improved TechTree Screen - VP EUI tech tree",ContextPtr,os.clock(),[[
 _____         _   _____
|_   _|__  ___| |_|_   _| __ ___  ___
  | |/ _ \/ __| '_ \| || '__/ _ \/ _ \
  | |  __/ (__| | | | || | |  __/  __/
  |_|\___|\___|_| |_|_||_|  \___|\___|
]])

-- Options for VP
local showDiscoveredBy = false -- afw Show number of met civs who have discovered this tech
local showTotalTurns = true	-- afw Show total turns when techs queued

g_UseSmallIcons = true

include( "TechButtonInclude" )
local IconHookup = IconHookup
local AddSmallButtonsToTechButton = AddSmallButtonsToTechButton

include( "TechHelpInclude" )
local GetHelpTextForTech = GetHelpTextForTech

-------------------------------
-- minor lua optimizations
-------------------------------
local math_abs = math.abs
local math_max = math.max
local math_min = math.min
local math_ceil = math.ceil

local ButtonPopupTypes = ButtonPopupTypes
local ContextPtr = ContextPtr
local Controls = Controls
local Events = Events
local Game = Game
local GameInfo = EUI.GameInfoCache or GameInfo -- warning! use iterator ONLY with table field conditions, NOT string SQL query
local GameInfoTypes = GameInfoTypes
local KeyEvents_KeyDown = KeyEvents.KeyDown
local Keys = Keys
local L = Locale.ConvertTextKey
local Locale = Locale
local Mouse = Mouse
local Network_SendResearch = Network.SendResearch
local Players = Players
local PopupPriority_InGameUtmost = PopupPriority.InGameUtmost
local Teams = Teams
local UI = UI
local UIManager = UIManager

local gk_mode = Players[0].GetNumTechsToSteal ~= nil

local g_scienceEnabled = not Game.IsOption(GameOptionTypes.GAMEOPTION_NO_SCIENCE)

local g_options = Modding.OpenUserData( "Enhanced User Interface Options", 1)
local g_popupInfoType, g_isAutoClose
local g_stealingTechTargetPlayerID, g_stealingTechTargetPlayer = -1

local g_NeedsFullRefresh = true
local g_RefreshRequested = false

local g_techButtons = {}
local g_eraBlocks = {}
local g_eraColumns = {}

local g_maxSmallButtons = 10 -- Original: 5

local g_EspionageViewMode
local g_activePlayerID, g_activePlayer, g_activeCivType, g_activeTeamID, g_activeTeam, g_activeTeamTechs

local g_connectorSizeX = 32	-- connector texture width
local g_connectorSizeY = 42	-- connector texture height
local g_connectorXshift = 12	-- horizontal connector texture shift
local g_connectorYshift = 15	-- vertical connector texture shift
local g_blockSizeX = 270	-- tech block width
local g_blockOffsetX = 64
local g_blockSpacingY = 68	-- tech block vertical spacing
local g_blockOffsetY = 0 - 5*g_blockSpacingY -- Original: 32 - 5*g_blockSpacingY
local g_blockSpacingX = g_blockSizeX + 96
local g_branchOffsetY1 = g_blockOffsetY + 12
local g_branchOffsetY2 = g_branchOffsetY1 - g_connectorYshift
local g_deltaHeight = g_connectorSizeY - g_connectorYshift
local g_pipeStartOffsetX = g_blockOffsetX + g_blockSizeX
local g_pipeEndOffsetX = g_blockOffsetX
local g_branchOffsetX1 = 0
local g_branchOffsetX2 = g_branchOffsetX1 - g_connectorXshift
local g_branchDeltaX = g_pipeEndOffsetX - g_branchOffsetX1
local g_coloredPipe = { x=1.0, y=1.0, z=0.0, w=0.5 }

local g_maxTechNameLength = 22 - Locale.Length(L"TXT_KEY_TURNS")

local freeString = L("TXT_KEY_FREE")
local lockedString = "[ICON_LOCKED]"

local CloseTechTree
local g_queueInfo = {} --afw
local g_blockedTechs = {} --afw
-------------------------------------------------
-- Tech Pipe Management
-------------------------------------------------

local function AddNewPipeIconWithoutColor( x, y )
	local newPipeInstance = {}
	ContextPtr:BuildInstanceForControl( "TechPipeInstance", newPipeInstance, Controls.TechTreeScrollPanel )
	local pipeIcon = newPipeInstance.TechPipeIcon
	pipeIcon:SetOffsetVal( x, y )
	return pipeIcon
end

local function AddNewPipeIconColored( x, y )
	local pipeIcon = AddNewPipeIconWithoutColor( x, y )
	pipeIcon:SetColor( g_coloredPipe )
	return pipeIcon
end

local function AddTechPipes( AddNewPipeIcon, techPairs )
	local function AddElbowPipe( x, y, tox, toy )
		local pipeIcon = AddNewPipeIcon( x, y )
		pipeIcon:SetTexture( "TechBranches.dds" )
		pipeIcon:SetTextureOffsetVal( tox, toy )
	end

	local function AddHorizontalPipe( x, y, length )
		local pipeIcon = AddNewPipeIcon( x, y )
		pipeIcon:SetSizeVal( length, g_connectorSizeY )
		pipeIcon:SetTexture( "TechBranchH.dds" )
	end

	-- add straight connectors first
	for row in techPairs() do
		local prereq = GameInfo.Technologies[row.PrereqTech]
		local tech = GameInfo.Technologies[row.TechType]
		if tech and prereq then
			local x1 = prereq.GridX*g_blockSpacingX + g_pipeStartOffsetX
			local x2 = tech.GridX*g_blockSpacingX + g_pipeEndOffsetX

			local height = math_abs( tech.GridY - prereq.GridY ) * g_blockSpacingY - g_deltaHeight

			-- vertical connector
			if height > 0 then
				local x = x2 - g_branchDeltaX
				local pipeIcon = AddNewPipeIcon( x, ( (tech.GridY + prereq.GridY) * g_blockSpacingY - g_connectorYshift ) / 2 + g_branchOffsetY1 )
				pipeIcon:SetTexture( "TechBranchV.dds" )
				pipeIcon:SetSizeVal( g_connectorSizeX, height )
				AddHorizontalPipe( x1, prereq.GridY*g_blockSpacingY + g_branchOffsetY1, x - x1 - g_connectorXshift )
				x = x + g_connectorSizeX
				AddHorizontalPipe( x, tech.GridY*g_blockSpacingY + g_branchOffsetY1, x2 - x )
			else
				AddHorizontalPipe( x1, prereq.GridY*g_blockSpacingY + g_branchOffsetY1, x2 - x1 )
			end
		end
	end

	-- add elbow connectors on top
	for row in techPairs() do
		local prereq = GameInfo.Technologies[row.PrereqTech]
		local tech = GameInfo.Technologies[row.TechType]
		if tech and prereq then
			local x = tech.GridX*g_blockSpacingX
			local y1 = prereq.GridY*g_blockSpacingY
			local y2 = tech.GridY*g_blockSpacingY

			if y1 < y2 then -- elbow case ������|__

				AddElbowPipe( x + g_branchOffsetX2, y1 + g_branchOffsetY1, 72, 0 )	--topRightTexture  �|
				AddElbowPipe( x + g_branchOffsetX1, y2 + g_branchOffsetY2 , 0, 72 )	--bottomLeftTexture |_

			elseif y1 > y2 then -- elbow case ______|��

				AddElbowPipe( x + g_branchOffsetX2, y1 + g_branchOffsetY2, 72, 72 )	--bottomRightTexture _|
				AddElbowPipe( x + g_branchOffsetX1, y2 + g_branchOffsetY1, 0, 0 )	--topLeftTexture |�
			end
		end
	end
end

-------------------------------------------------
-- Mouse Click Management
-------------------------------------------------

local function TechSelected( techID )
	if GameInfo.Technologies[ techID ] and not g_EspionageViewMode then
		local shift = UIManager:GetShift()
		if g_stealingTechTargetPlayer then
			if g_activePlayer:CanResearch( techID )
				and g_activePlayer:GetNumTechsToSteal( g_stealingTechTargetPlayerID ) > 0
				and Teams[ g_stealingTechTargetPlayer:GetTeam() ]:IsHasTech( techID )
			then
				Network_SendResearch( techID, 0, g_stealingTechTargetPlayerID, shift )
				CloseTechTree()
			end
		else
			Network_SendResearch( techID, g_activePlayer:GetNumFreeTechs(), -1, shift )
			if g_isAutoClose and not shift and g_popupInfoType == ButtonPopupTypes.BUTTONPOPUP_CHOOSETECH then
				CloseTechTree()
			end
		end
	end
end

local function TechPedia( techID )
	local tech = GameInfo.Technologies[ techID ] or {}
	Events.SearchForPediaEntry( tech.Description )
end

local function setTechToolTip( techID, _, button )
	button:SetToolTipString( GetHelpTextForTech( techID, g_EspionageViewMode, g_activePlayerID ) )
end

-------------------------------------------------
-- Display Refresh Management
-------------------------------------------------

local function RefreshDisplayOfSpecificTech( tech )
	local techID = tech.ID
--  print("RefreshDisplayOfSpecificTech:", techID, L(tech.Description), "  ", g_NeedsFullRefresh)
	local thisTechButton = g_techButtons[ techID ]
	local canResearchThisTech = g_activePlayer:CanResearch( techID )
	local turnText = L( "TXT_KEY_STR_TURNS", g_activePlayer:GetResearchTurnsLeft( techID, true ) )
	local researchPerTurn = g_activePlayer:GetScienceTimes100()

	if showDiscoveredBy then --afw
--		local modifier = g_activePlayer:CalculateResearchModifier(techID)
--		turnText = turnText .. modifier
		local alive = 0
		local met = 0
		local discovered = 0
		for playerID, player in ipairs(Players) do
			if player:IsEverAlive() and player:IsAlive() and playerID < GameDefines.MAX_MAJOR_CIVS then
				alive = alive + 1
				local team = player:GetTeam()
				if playerID ~= g_activePlayerID and g_activeTeam:IsHasMet( team ) then
					met = met + 1
					if (Teams[team]:IsHasTech(techID)) then
						discovered = discovered + 1
					end
				end
			end
		end
		if discovered > 0 then
			thisTechButton.Discovered:SetText(discovered)
		end
	end
	if showTotalTurns then --afw
		if g_activePlayer:GetLengthResearchQueue() > 1 then
			local pos = g_activePlayer:GetQueuePosition( techID )
			if pos > 1 then
				turnText = turnText .. " (" .. g_queueInfo[pos] .. ")"
			end
		end
	end
	--print("RefreshDisplayOfSpecificTech afw Stuff done")
	-- Rebuild the small buttons if needed
	if g_NeedsFullRefresh then
		AddSmallButtonsToTechButton( thisTechButton, tech, g_maxSmallButtons, 45, g_activePlayerID)
	end
	if g_EspionageViewMode then
		thisTechButton.TechButton:SetDisabled(true);
	else
		thisTechButton.TechButton:RegisterCallback( Mouse.eMouseEnter, setTechToolTip )
		thisTechButton.TechButton:SetDisabled(false);
	end
	
	local showAlreadyResearched, showFreeTech, showCurrentlyResearching, showAvailable, showUnavailable, showLocked, queueUpdate, queueText, turnLabel, isClickable

	if g_activeTeamTechs:HasTech( techID ) then
	-- the active player already has this tech
		showAlreadyResearched = true
		-- update the era marker for this tech
		(g_eraColumns[GameInfoTypes[tech.Era]] or {}).researched = true

	elseif (g_stealingTechTargetPlayer or g_activePlayer:GetNumFreeTechs() > 0) and not g_EspionageViewMode then
	-- Stealing a tech or Choosing a free tech
		if canResearchThisTech and (
			( g_stealingTechTargetPlayer and Teams[ g_stealingTechTargetPlayer:GetTeam() ]:IsHasTech( techID ) )
			or (not g_stealingTechTargetPlayer and (not gk_mode or g_activePlayer:CanResearchForFree( techID ))) )
		then
			showFreeTech = true
			turnLabel = thisTechButton.FreeTurns
			queueText = freeString	-- update queue number to say "FREE"
			isClickable = true
		else
			showLocked = true
		end

	-- the active player is currently researching this one
	elseif g_activePlayer:GetCurrentResearch() == techID then
		showCurrentlyResearching = true
		turnLabel = thisTechButton.CurrentlyResearchingTurns
		queueUpdate = g_activePlayer:GetLengthResearchQueue() > 1	-- update queue number if needed
		isClickable = true -- to clear research queue
--[[
		-- turn on the meter
		local currentResearchProgress = g_activePlayer:GetResearchProgressTimes100( techID ) / 100
		local researchNeeded = g_activePlayer:GetResearchCost( techID )
		local currentResearchPlusThisTurn = currentResearchProgress + researchPerTurn
		local researchProgressPercent = currentResearchProgress / researchNeeded
		local researchProgressPlusThisTurnPercent = math_min( 1, currentResearchPlusThisTurn / researchNeeded )
--]]
	-- the active player can research this one right now if he wants
	elseif canResearchThisTech and g_scienceEnabled then
		showAvailable = true
		turnLabel = thisTechButton.AvailableTurns
		queueUpdate = true	-- update queue number if needed
		isClickable = true

	elseif g_activePlayer:CanEverResearch( techID ) and g_scienceEnabled then
	-- currently unavailable
		showUnavailable = true
		queueUpdate = true	-- update queue number if needed
		turnLabel = thisTechButton.UnavailableTurns
		isClickable = true  -- shift clickable
	else
		showLocked = true
	end
	local showLarge = g_maxSmallButtons > 5 and thisTechButton["B6"] and not thisTechButton["B6"]:IsHidden() --afw
	if showLarge then
		if g_blockedTechs[techID] then
			print("Couldn't expand", techID, L(tech.Description))
			if thisTechButton["B6"] then thisTechButton["B6"]:SetHide(true) end
			if thisTechButton["B7"] then thisTechButton["B7"]:SetHide(true) end
			if thisTechButton["B8"] then thisTechButton["B8"]:SetHide(true) end
			if thisTechButton["B9"] then thisTechButton["B9"]:SetHide(true) end
			if thisTechButton["B10"] then thisTechButton["B10"]:SetHide(true) end
		else -- Magic numbers? Well, thy replace similar in the xml!
			thisTechButton.TechButton:SetSizeY(102)
			thisTechButton.AlreadyResearched:SetSizeY(102)
			thisTechButton.AlreadyResearchedFrame:SetSizeY(106)
			thisTechButton.AlreadyResearchedAnim3:SetSizeY(102)
			thisTechButton.CurrentlyResearching:SetSizeY(102)
			thisTechButton.CurrentlyResearchingFrame:SetSizeY(106)
			thisTechButton.CurrentlyResearchingAnim1:SetSizeY(102)
			thisTechButton.CurrentlyResearchingAnim2:SetSizeY(102)
			thisTechButton.CurrentlyResearchingAnim3:SetSizeY(102)
			thisTechButton.Available:SetSizeY(102)
			thisTechButton.AvailableFrame:SetSizeY(106)
			thisTechButton.AvailableAnim3:SetSizeY(102)
			thisTechButton.Unavailable:SetSizeY(102)
			thisTechButton.UnavailableFrame:SetSizeY(106)
			thisTechButton.UnavailableAnim3:SetSizeY(102)
			thisTechButton.Locked:SetSizeY(102)
			thisTechButton.LockedFrame:SetSizeY(106)
			thisTechButton.FreeTech:SetSizeY(102)
			thisTechButton.FreeTechFrame:SetSizeY(106)
			thisTechButton.FreeTechAnim3:SetSizeY(102)
			thisTechButton.StuffBox:SetSizeY(76)
		end
	end
	thisTechButton.AlreadyResearched:SetHide( not showAlreadyResearched )
	thisTechButton.FreeTech:SetHide( not showFreeTech )
	thisTechButton.CurrentlyResearching:SetHide( not showCurrentlyResearching )
	thisTechButton.Available:SetHide( not showAvailable )
	thisTechButton.Unavailable:SetHide( not showUnavailable )
	thisTechButton.Locked:SetHide( not showLocked )
	if showLocked then
		queueText = lockedString	-- have queue number say "LOCKED"
	elseif queueUpdate then
		local queuePosition = g_activePlayer:GetQueuePosition( techID )
		if queuePosition ~= -1 then
			queueText = queuePosition
		end
	end
	if queueText then
		thisTechButton.TechQueueLabel:SetText( queueText )
	end
	thisTechButton.TechQueue:SetHide( not queueText )
	--print("RefreshDisplayOfSpecificTech Click stuff next")
	if isClickable then
		thisTechButton.TechButton:RegisterCallback( Mouse.eLClick, TechSelected )
		for buttonNum = 1, g_maxSmallButtons do
			thisTechButton["B"..buttonNum]:RegisterCallback( Mouse.eLClick, TechSelected )
		end
	else
		thisTechButton.TechButton:ClearCallback( Mouse.eLClick )
		for buttonNum = 1, g_maxSmallButtons do
			thisTechButton["B"..buttonNum]:ClearCallback( Mouse.eLClick )
		end
	end
	if turnLabel then
		if researchPerTurn > 0 and g_scienceEnabled then
			turnLabel:SetText( turnText )
			turnLabel:SetHide( false )
		else
			turnLabel:SetHide( true )
		end
	end
end

local function QueueInfo() -- afw
	g_queueInfo = {}
	local researchPerTurn = g_activePlayer:GetScienceTimes100() / 100
	local overflow = g_activePlayer:GetOverflowResearchTimes100() / 100
	for tech in GameInfo.Technologies() do
		local techID = tech.ID
		local pos = g_activePlayer:GetQueuePosition( techID )
		if pos > 0 then
			local currentResearchProgress = g_activePlayer:GetResearchProgressTimes100( techID ) / 100
			local researchNeeded = g_activePlayer:GetResearchCost( techID )
			local remaining = researchNeeded + overflow - currentResearchProgress
--			print("AFW Tech:", pos, techID, currentResearchProgress, researchNeeded, overflow, remaining, tech.Description )
			g_queueInfo[pos] = remaining
		end
	end
	g_queueInfo[1] = g_queueInfo[1] - overflow
	local totalcost = 0
	for pos,cost in ipairs(g_queueInfo) do
		totalcost = totalcost + cost
		local turns = math_ceil(totalcost / math_max(researchPerTurn, 1))
		g_queueInfo[pos] = turns
		--print("AFW Queue:", pos, cost, totalcost, turns)
	end
end

local function RefreshDisplayNow()
	--print("TechTree - RefreshDisplayNow Start - Full refresh=", g_NeedsFullRefresh)
	--g_RefreshRequested = false
	ContextPtr:ClearUpdate()
	--print("TechTree - RefreshDisplayNow(1)")

	if g_activePlayer:GetLengthResearchQueue() > 1 and showTotalTurns then
		QueueInfo()
	end
	
	-- reset the era panels
	for thisEra = 0, #g_eraBlocks  do
		if g_eraColumns[thisEra] then
			g_eraColumns[thisEra].researched = false;
		end
	end
	
	--print("TechTree - RefreshDisplayNow(2)")
	for tech in GameInfo.Technologies() do
		RefreshDisplayOfSpecificTech( tech )
	end

	-- update the era panels
	local highestEra = 0
	--print("TechTree - RefreshDisplayNow(3)")
	for thisEra = 0, #g_eraBlocks do
		if g_eraColumns[thisEra] and g_eraColumns[thisEra].researched then
			highestEra = thisEra
		end
	end
	--print("TechTree - RefreshDisplayNow(4)")
	for thisEra = 0, #g_eraBlocks do
		local thisEraBlockInstance = g_eraBlocks[thisEra]
		thisEraBlockInstance.OldBar:SetHide( thisEra >= highestEra )
		thisEraBlockInstance.CurrentBlock:SetHide( thisEra ~= highestEra )
		thisEraBlockInstance.CurrentTop:SetHide( thisEra ~= highestEra )
		thisEraBlockInstance.FutureBlock:SetHide( thisEra <= highestEra )
	end

	g_NeedsFullRefresh = false
	--print("TechTree - RefreshDisplayNow End")
end

local function RefreshDisplay(x)
	--print("RefreshDisplay:",x)
	RefreshDisplayNow() --afw
	--[[
	if not g_RefreshRequested then
		g_RefreshRequested = true
		ContextPtr:SetUpdate( RefreshDisplayNow )
	end
	--]]
end


-------------------------------------------------
-- find the range of columns that each era takes
-------------------------------------------------
for tech in GameInfo.Technologies() do
	local eraID = GameInfoTypes[tech.Era]
	local eraColumn = g_eraColumns[eraID]
	if not eraColumn then
		g_eraColumns[eraID] = { minGridX = tech.GridX, maxGridX = tech.GridX, researched = false }
	else
		if tech.GridX < eraColumn.minGridX then
			eraColumn.minGridX = tech.GridX
		end
		if tech.GridX > eraColumn.maxGridX then
			eraColumn.maxGridX = tech.GridX
		end
	end
end

-------------------------------------------------
-- add the era panels to the background
-------------------------------------------------
local eraBlockX = -g_blockSpacingX-32
for era in GameInfo.Eras() do

	local thisEraBlockInstance = {}
	ContextPtr:BuildInstanceForControl( "EraBlockInstance", thisEraBlockInstance, Controls.EraStack )
	-- store this panel off for later
	g_eraBlocks[era.ID] = thisEraBlockInstance

	-- add the correct text for this era panel
	local localizedLabel = L( era.Description )
	thisEraBlockInstance.OldLabel:SetText( localizedLabel )
	thisEraBlockInstance.CurrentLabel:SetText( localizedLabel )
	thisEraBlockInstance.FutureLabel:SetText( localizedLabel )

	-- adjust the sizes of the era panels
	local eraBlockWidth = 0
	if g_eraColumns[era.ID] then
		eraBlockWidth = g_eraColumns[era.ID].maxGridX * g_blockSpacingX
		eraBlockWidth, eraBlockX = eraBlockWidth - eraBlockX, eraBlockWidth
	end

	thisEraBlockInstance.EraBlock:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.FrameBottom:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.OldBar:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.OldBlock:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.CurrentBlock:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.CurrentBlock1:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.CurrentBlock2:SetSizeX( eraBlockWidth )

	thisEraBlockInstance.CurrentTop:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.CurrentTop1:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.CurrentTop2:SetSizeX( eraBlockWidth )
	thisEraBlockInstance.FutureBlock:SetSizeX( eraBlockWidth )
end

-------------------------------------------------
-- add the tech button pipes
-------------------------------------------------
AddTechPipes( AddNewPipeIconWithoutColor, GameInfo.Technology_PrereqTechs )
AddTechPipes( AddNewPipeIconColored, GameInfo.Technology_ORPrereqTechs )

-------------------------------------------------
-- add the tech buttons
-------------------------------------------------
for tech in GameInfo.Technologies() do
	local thisTechButton = {}
	local techID = tech.ID
	ContextPtr:BuildInstanceForControl( "TechButtonInstance", thisTechButton, Controls.TechTreeScrollPanel )

	-- store this instance off for later
	g_techButtons[techID] = thisTechButton

	-- add the input handler to this button
	thisTechButton.TechButton:SetVoids( techID, -1 )
	thisTechButton.TechButton:RegisterCallback( Mouse.eRClick, TechPedia )
	thisTechButton.TechButton:RegisterCallback( Mouse.eMouseEnter, setTechToolTip )

	if g_scienceEnabled then
		thisTechButton.TechButton:RegisterCallback( Mouse.eLClick, TechSelected )
	end

	-- position
	thisTechButton.TechButton:SetOffsetVal( tech.GridX*g_blockSpacingX + g_blockOffsetX, tech.GridY*g_blockSpacingY + g_blockOffsetY )

	-- name
	local techName = Locale.TruncateString( L(tech.Description), g_maxTechNameLength, true )
	thisTechButton.AlreadyResearchedTechName:SetText( techName )
	thisTechButton.CurrentlyResearchingTechName:SetText( techName )
	thisTechButton.AvailableTechName:SetText( techName )
	thisTechButton.UnavailableTechName:SetText( techName )
	thisTechButton.LockedTechName:SetText( techName )
	thisTechButton.FreeTechName:SetText( techName )

	-- picture
	thisTechButton.TechPortrait:SetHide( not IconHookup( tech.PortraitIndex, 64, tech.IconAtlas, thisTechButton.TechPortrait ) )

	for buttonNum = 1, g_maxSmallButtons do
		thisTechButton["B"..buttonNum]:SetVoid1( techID )
	end
end

-------------------------------------------------
-- Resize the panel to fit the contents, and the scroll bar for the display size
-------------------------------------------------
Controls.TechTreeScrollBar:SetSizeX( Controls.TechTreeScrollPanel:GetSizeX() - 150 )
Controls.EraStack:CalculateSize()
Controls.EraStack:ReprocessAnchoring()
Controls.TechTreeScrollPanel:CalculateInternalSize()

-------------------------------------------------
-- Find techs without space to grow (must be before InitActivePlayerData)
-------------------------------------------------
for tech in GameInfo.Technologies() do --afw
	for tech2 in GameInfo.Technologies() do
		if tech.GridX == tech2.GridX and ( tech.GridY == tech2.GridY + 1 or tech.GridY == tech2.GridY - 1) then
			g_blockedTechs[tech.ID] = true
			print("Can't expand tech", tech.ID, L(tech.Description))
		end
	end
end

-------------------------------------------------
-- Initialize active player data
-------------------------------------------------
local function InitActivePlayerData(OverridePlayer)
	--print("TechTree - InitActivePlayerData")
	g_activePlayerID = Game.GetActivePlayer()
	if OverridePlayer then
		g_activePlayerID = OverridePlayer
	end
	g_activePlayer = Players[g_activePlayerID]
	g_activeTeamID = g_activePlayer:GetTeam()
	g_activeTeam = Teams[g_activeTeamID]
	g_activeTeamTechs = g_activeTeam:GetTeamTechs()

	g_NeedsFullRefresh = true
	return RefreshDisplay("Init")
end
InitActivePlayerData()

-------------------------------------------------
-- Close Tech Tree
-------------------------------------------------
CloseTechTree = function()
	if g_popupInfoType then
		Events.SerialEventGameMessagePopupProcessed.CallImmediate(g_popupInfoType, 0)
		g_popupInfoType = false
		UI.decTurnTimerSemaphore()
	end
	if g_EspionageViewMode then
		-- reset to show the tech tree of the currently active player next time
		InitActivePlayerData()
	end
	g_stealingTechTargetPlayerID, g_stealingTechTargetPlayer = -1
	UIManager:DequeuePopup( ContextPtr )
end
Controls.CloseButton:RegisterCallback( Mouse.eLClick, CloseTechTree )

-------------------------------------------------
-- Open Tech Tree
-------------------------------------------------
Events.SerialEventGameMessagePopup.Add(
function( popupInfo )
	--print("Popup Type:", (popupInfo and popupInfo.Type or "none"))
	--[[
	for a,b in pairs(popupInfo) do
		print(a,b)
	end
	--]]
	if popupInfo.Type == ButtonPopupTypes.BUTTONPOPUP_CHOOSETECH then
		g_stealingTechTargetPlayerID = -1
	elseif popupInfo.Type == ButtonPopupTypes.BUTTONPOPUP_TECH_TREE or popupInfo.Type == ButtonPopupTypes.BUTTONPOPUP_CHOOSE_TECH_TO_STEAL then
		g_stealingTechTargetPlayerID = gk_mode and popupInfo.Data2 or -1
	else
		return
	end
	
	if popupInfo.Type == ButtonPopupTypes.BUTTONPOPUP_TECH_TREE and popupInfo.Data4 > 0 then
		-- Espionage view mode
		g_EspionageViewMode = true;
		InitActivePlayerData(popupInfo.Data5)
		print("Espionage View Mode, showing tech tree for Player " .. g_activePlayerID)	
	else
		g_EspionageViewMode = false;
		g_activePlayerID = Game.GetActivePlayer();
	end
	
	g_stealingTechTargetPlayer = Players[ g_stealingTechTargetPlayerID ] -- g_activePlayer:GetNumTechsToSteal( g_stealingTechTargetPlayerID ) > 0

	Events.SerialEventGameMessagePopupShown(popupInfo)

	if g_popupInfoType then
	--print("Closing from Popup")
		return CloseTechTree()
	else
		g_popupInfoType = popupInfo.Type
		UIManager:QueuePopup( ContextPtr, PopupPriority_InGameUtmost )
		UI.incTurnTimerSemaphore()
		-- initialize scrollbar position
		if Controls.TechTreeScrollPanel:GetScrollValue() == 0 then
			local pPlayer = Players[Game.GetActivePlayer()]
			local techID = pPlayer:GetCurrentResearch()
			local dx = 0
			if techID < 0 then
				techID = Teams[pPlayer:GetTeam()]:GetTeamTechs():GetLastTechAcquired()
				dx = 1
			end
			local tech = GameInfo.Technologies[techID]
			local x = tech and tech.GridX
			if x then
				Controls.TechTreeScrollPanel:SetScrollValue( math_min(1,math_max(0,( (x + dx)*g_blockSpacingX/Controls.TechTreeScrollPanel:GetSizeX() - 0.5) / math_max(1,1/Controls.TechTreeScrollPanel:GetRatio() - 1) ) ) )
			end
		end
		return RefreshDisplay("Popup")
	end
end)

-------------------------------------------------
-- Input processing
-------------------------------------------------

ContextPtr:SetInputHandler(
function ( uiMsg, wParam )--, lParam )
	if uiMsg == KeyEvents_KeyDown
		and (wParam == Keys.VK_ESCAPE or wParam == Keys.VK_RETURN)
	then
		CloseTechTree()
		return true
	end
end)

local function ProcessEvent()
	if g_popupInfoType then
		RefreshDisplay("Event")
	else
		--print("Event ignored")
	end
end

Events.SerialEventResearchDirty.Add( ProcessEvent )

local function UpdateOptions()
--	g_isAdvisor = not ( g_options and g_options.GetValue and g_options.GetValue( "CityAdvisor" ) == 0 )
	g_isAutoClose = not ( g_options and g_options.GetValue and g_options.GetValue( "AutoClose" ) == 0 )
	return RefreshDisplay("Options")
end
UpdateOptions()
Events.GameOptionsChanged.Add( UpdateOptions )

Events.GameplaySetActivePlayer.Add( function()
	-- So some extra stuff gets re-built on the refresh call
	if g_popupInfoType then
		CloseTechTree() -- so the next active player does not have to
	end
	InitActivePlayerData()
end)
local function OnConstruction( ePlayer, eCity, eBuilding) --afw
	local pBuilding = GameInfo.Buildings[eBuilding]
	if GameInfo.BuildingClasses[pBuilding.BuildingClass].MaxGlobalInstances == 1 then
		g_NeedsFullRefresh = true
	end
end
GameEvents.CityConstructed.Add(OnConstruction)

print("Finished loading Improved TechTree Screen - VP EUI tech tree",os.clock())
end)
