-------------------------------
-- TopPanel.lua
-------------------------------
--Additions by BlakeTheGreat are on lines 18-20, 22-101, 229-279, 973-1189.
--To find the beggining of the additions, press cntrl+f, check "match case" and search for "ADDED"
--To find the end of the additions, just search for "END ADD"
-------------------------------
-------------------------------
-------------------------------
-------------------------------
-------------------------------




--ADDED
local hasGP = false;
--END ADD

---------------------------------------------------
-----------ADDED helper functions------------------
---------------------------------------------------

--check if player has any GPs being built
function checkIfGP(player) 
	for pCity in player:Cities() do
		for pSpecialistInfo in GameInfo.Specialists() do	
			local iSpecialistIndex =  pSpecialistInfo.ID;			
			local iProgress = pCity:GetSpecialistGreatPersonProgress(iSpecialistIndex);	
			if(iProgress>0) then
				hasGP = true;
				return;
			end
		end
	end
end

--return a dictionary of all the GPs from each city being built in the format: [{city, GP} = progress]
function listProgress(player)
	progresses = {};
	for pCity in player:Cities() do
		for pSpecialistInfo in GameInfo.Specialists() do	
			local iSpecialistIndex =  pSpecialistInfo.ID;			
			local iProgress = pCity:GetSpecialistGreatPersonProgress(iSpecialistIndex);	
			if(iProgress>0) then 
				progresses[{pCity, pSpecialistInfo}] = iProgress
			end
		end
	end
	return progresses;
end

--given a specialistInfo object, returns the name of the great person
function getGPName(specialistInfo)
	local labelText = "";
	local condition = "Type = '" .. specialistInfo.GreatPeopleUnitClass .. "'";
	for unitClass in GameInfo.UnitClasses( condition ) do
		labelText = Locale.ConvertTextKey(unitClass.Description);
	end
	return labelText;
end

--given a city and GP, returns the progress per turn
function getRateOfChange(city, specialistInfo, player)
	local iCount = city:GetSpecialistCount( specialistInfo.ID );
	--print("Rate of change? "..tostring(specialistInfo.GreatPeopleRateChange));
	local iGPPChange = specialistInfo.GreatPeopleRateChange * iCount * 100;
	for building in GameInfo.Buildings() do
		local buildingID = building.ID;
		if building.SpecialistType == specialistInfo.Type then
			if (city:IsHasBuilding(buildingID)) then
				iGPPChange = iGPPChange + building.GreatPeopleRateChange * 100;
			end
		end
	end
	--print("Initial iGPP Change = "..tostring(iGPPChange));
	if iGPPChange > 0 then
		local iMod = 0;
		iMod = iMod + city:GetGreatPeopleRateModifier();
		iMod = iMod + player:GetGreatPeopleRateModifier();
		if (specialistInfo.GreatPeopleUnitClass == "UNITCLASS_SCIENTIST") then
			iMod = iMod + player:GetTraitGreatScientistRateModifier();
		end
		--print("iMod = "..iMod);
		iGPPChange = (iGPPChange * (100 + iMod)) / 100;
		--print("Final GPP Change = "..tostring(iGPPChange));
		--print("return "..math.floor(iGPPChange/100));
		--(+X GPICON) where x = rate of change
		return math.floor(iGPPChange/100);
		
		--strToolTipText = strToolTipText .. " (+" .. math.floor(iGPPChange/100) .. "[ICON_GREAT_PEOPLE])";	
	else
		return 0;
	end
end

---------------------------------------------------
-----------------END ADD---------------------------
---------------------------------------------------

function UpdateData()

	local iPlayerID = Game.GetActivePlayer();

	if( iPlayerID >= 0 ) then
		local pPlayer = Players[iPlayerID];
		local pTeam = Teams[pPlayer:GetTeam()];
		local pCity = UI.GetHeadSelectedCity();
		local pTeamTechs = pTeam:GetTeamTechs();
		
		if (pPlayer:GetNumCities() > 0) then
			
			Controls.TopPanelInfoStack:SetHide(false);
			
			-----------------------------
			-- Update science stats
			-----------------------------
			
			local sciencePerTurn = pPlayer:GetScience();
			
			if (pCity ~= nil and UI.IsCityScreenUp()) then		
				Controls.MenuButton:SetText(Locale.ToUpper(Locale.ConvertTextKey("TXT_KEY_RETURN")));
				Controls.MenuButton:SetToolTipString(Locale.ConvertTextKey("TXT_KEY_CITY_SCREEN_EXIT_TOOLTIP"));
			else
				Controls.MenuButton:SetText(Locale.ToUpper(Locale.ConvertTextKey("TXT_KEY_MENU")));
				Controls.MenuButton:SetToolTipString(Locale.ConvertTextKey("TXT_KEY_MENU_TOOLTIP"));
			end
			
			local strScienceText;
			
			-- No Science
			if (sciencePerTurn <= 0) then
				strScienceText = string.format("[COLOR:255:60:60:255]" .. Locale.ConvertTextKey("TXT_KEY_NO_SCIENCE") .. "[/COLOR]");
			-- We have science
			elseif (pPlayer:GetCurrentResearch() == -1) then
				strScienceText = "[COLOR:255:60:0:255]" .. Locale.ConvertTextKey("TXT_KEY_NO_SCIENCE") .. "[/COLOR]";
			else
				strScienceText = string.format("+%i", sciencePerTurn);

				local iGoldPerTurn = pPlayer:CalculateGoldRate();
				
                local techID = pPlayer:GetCurrentResearch();
                local turnsLeft = pPlayer:GetResearchTurnsLeft( techID, true );
                local got = pTeamTechs:GetResearchProgress(techID);
                local needed = pTeamTechs:GetResearchCost(techID);
                
                strScienceText = string.format("%d/%d (%dt +%i)", got, needed, turnsLeft, sciencePerTurn);
                
				-- Gold being deducted from our Science
				if (pPlayer:GetGold() + iGoldPerTurn < 0) then
					strScienceText = "[COLOR:255:60:0:255]" .. strScienceText .. "[/COLOR]";
				-- Normal Science state
				else
					strScienceText = "[COLOR:33:190:247:255]" .. strScienceText .. "[/COLOR]";
				end
			end
			
			strScienceText = "[ICON_RESEARCH]" .. strScienceText;
			
			Controls.SciencePerTurn:SetText(strScienceText);
			
			-----------------------------
			-- Update gold stats
			-----------------------------
			local iTotalGold = pPlayer:GetGold();
			local iGoldPerTurn = pPlayer:CalculateGoldRate();
			
			-- Accounting for positive or negative GPT - there's obviously a better way to do this.  If you see this comment and know how, it's up to you ;)
			-- Text is White when you can buy a Plot
			--if (iTotalGold >= pPlayer:GetBuyPlotCost(-1,-1)) then
				--if (iGoldPerTurn >= 0) then
					--strGoldStr = string.format("[COLOR:255:255:255:255]%i (+%i)[/COLOR]", iTotalGold, iGoldPerTurn)
				--else
					--strGoldStr = string.format("[COLOR:255:255:255:255]%i (%i)[/COLOR]", iTotalGold, iGoldPerTurn)
				--end
			---- Text is Yellow or Red when you can't buy a Plot
			--else
			local strGoldStr = Locale.ConvertTextKey("TXT_KEY_TOP_PANEL_GOLD", iTotalGold, iGoldPerTurn);
			--end
			
			Controls.GoldPerTurn:SetText(strGoldStr);
			
			-----------------------------
			-- Update Happiness
			-----------------------------
			local iHappiness = pPlayer:GetExcessHappiness();
			local strHappiness;
			local tHappinessTextColor;

			-- Empire is Happiness
			if (not pPlayer:IsEmpireUnhappy()) then
				strHappiness = string.format("[ICON_HAPPINESS_1][COLOR:60:255:60:255]%i[/COLOR]", iHappiness);
				
			-- Empire Really Unhappy
			elseif (pPlayer:IsEmpireVeryUnhappy()) then
				strHappiness = string.format("[ICON_HAPPINESS_4][COLOR:255:60:60:255]%i[/COLOR]", -iHappiness);
				
			-- Empire Unhappy
			else
				strHappiness = string.format("[ICON_HAPPINESS_3][COLOR:255:60:60:255]%i[/COLOR]", -iHappiness);
			end

			Controls.HappinessString:SetText(strHappiness);
			
			-----------------------------
			-- Update Golden Age Info
			-----------------------------

			local strGoldenAgeStr;
			local gturns;
			if (pPlayer:GetGoldenAgeTurns() > 0) then
				strGoldenAgeStr = string.format(Locale.ToUpper(Locale.ConvertTextKey("TXT_KEY_GOLDEN_AGE_ANNOUNCE")) .. " (%i)", pPlayer:GetGoldenAgeTurns());
			else
				if (pPlayer:GetGoldenAgeProgressThreshold() < pPlayer:GetGoldenAgeProgressMeter()) then
					strGoldenAgeStr = string.format("%i/%i", pPlayer:GetGoldenAgeProgressMeter(), pPlayer:GetGoldenAgeProgressThreshold());
				else
					gturns = math.ceil((pPlayer:GetGoldenAgeProgressThreshold() - pPlayer:GetGoldenAgeProgressMeter()) / pPlayer:GetExcessHappiness());
					strGoldenAgeStr = string.format("%i/%i (%it)", pPlayer:GetGoldenAgeProgressMeter(), pPlayer:GetGoldenAgeProgressThreshold(), gturns);
				end
			end
			
			strGoldenAgeStr = "[ICON_GOLDEN_AGE][COLOR:255:255:255:255]" .. strGoldenAgeStr .. "[/COLOR]";
			
			Controls.GoldenAgeString:SetText(strGoldenAgeStr);
			
			-----------------------------
			-- Update Culture
			-----------------------------

			local strCultureStr;
			local sturns;
			if (pPlayer:GetNextPolicyCost() > 0) then
				if (pPlayer:GetNextPolicyCost() < pPlayer:GetJONSCulture()) then
					strCultureStr = string.format("%i/%i (+%i)", pPlayer:GetJONSCulture(), pPlayer:GetNextPolicyCost(), pPlayer:GetTotalJONSCulturePerTurn());
				else
					sturns = math.ceil((pPlayer:GetNextPolicyCost() - pPlayer:GetJONSCulture()) / pPlayer:GetTotalJONSCulturePerTurn());
					strCultureStr = string.format("%i/%i (%it +%i)", pPlayer:GetJONSCulture(), pPlayer:GetNextPolicyCost(), sturns, pPlayer:GetTotalJONSCulturePerTurn());
				end
				--strCultureStr = string.format("%i/%i +%i", pPlayer:GetJONSCulture(), pPlayer:GetNextPolicyCost(), pPlayer:GetTotalJONSCulturePerTurn());
			else
				strCultureStr = string.format("%i (+%i)", pPlayer:GetJONSCulture(), pPlayer:GetTotalJONSCulturePerTurn());
			end
			
			strCultureStr = "[ICON_CULTURE][COLOR:255:0:255:255]" .. strCultureStr .. "[/COLOR]";
			
			Controls.CultureString:SetText(strCultureStr);
			


			---------------------------------------------------
			-----------ADDED Update Great People---------------
			---------------------------------------------------
			
			local strGreatPeopleStr = "";

			if(not(hasGP)) then
				checkIfGP(pPlayer);
			end


			if(hasGP) then
				local GPList = listProgress(pPlayer);

				if(GPList == nil) then
					hasGP = false;
				end

				Controls.GreatPeopleString:SetHide(false);
				
				--Find city/GP pair closest to production.
				local maxKey;
				local min = math.huge;
				for k,v in pairs(GPList) do
					local threshold = k[1]:GetSpecialistUpgradeThreshold();
					if(threshold-v < min) then
						min = threshold-v;
						maxKey = k;
					end
				end

				--break it up into variables
				local theCity = maxKey[1];
				local pSpecialistInfo = maxKey[2];
				local cityName = Locale.ToUpper(Locale.ConvertTextKey(theCity:GetNameKey()));
				local GPName = getGPName(pSpecialistInfo);
				local threshold = theCity:GetSpecialistUpgradeThreshold();

				local rateOfChange = 0;
				rateOfChange = getRateOfChange(theCity, pSpecialistInfo, pPlayer);

				strGreatPeopleStr = strGreatPeopleStr .. "[ICON_GREAT_PEOPLE][COLOR:225:225:225:255] " .. GPList[maxKey] .. "/" .. threshold .. " (+".. rateOfChange .. ")[/COLOR]";

				Controls.GreatPeopleString:SetText(strGreatPeopleStr);

			else
				Controls.GreatPeopleString:SetHide(true);
			end
			---------------------------------------------------
			---------------------END ADD-----------------------
			---------------------------------------------------



			-----------------------------
			-- Update Resources
			-----------------------------
			local pResource;
			local bShowResource;
			local iNumAvailable;
			local iNumUsed;
			local iNumTotal;
			
			local strResourceText = "";
			local strTempText = "";
			
			for pResource in GameInfo.Resources() do
				local iResourceLoop = pResource.ID;
				
				if (Game.GetResourceUsageType(iResourceLoop) == ResourceUsageTypes.RESOURCEUSAGE_STRATEGIC) then
					
					bShowResource = false;
					
					if (pTeam:GetTeamTechs():HasTech(GameInfoTypes[pResource.TechReveal])) then
						if (pTeam:GetTeamTechs():HasTech(GameInfoTypes[pResource.TechCityTrade])) then
							bShowResource = true;
						end
					end
					
					iNumAvailable = pPlayer:GetNumResourceAvailable(iResourceLoop, true);
					iNumUsed = pPlayer:GetNumResourceUsed(iResourceLoop);
					iNumTotal = pPlayer:GetNumResourceTotal(iResourceLoop, true);
					
					if (iNumUsed > 0) then
						bShowResource = true;
					end
							
					if (bShowResource) then
						local text = Locale.ConvertTextKey(pResource.IconString);
						strTempText = string.format("%i %s   ", iNumAvailable, text);
						
						-- Colorize for amount available
						if (iNumAvailable > 0) then
							strTempText = "[COLOR_POSITIVE_TEXT]" .. strTempText .. "[ENDCOLOR]";
						elseif (iNumAvailable < 0) then
							strTempText = "[COLOR_WARNING_TEXT]" .. strTempText .. "[ENDCOLOR]";
						end
						
						strResourceText = strResourceText .. strTempText;
					end
				end
			end
			
			Controls.ResourceString:SetText(strResourceText);
			
		-- No Cities, so hide science
		else
			
			Controls.TopPanelInfoStack:SetHide(true);
			
		end
		
		-- Update turn counter
		local turn = Locale.ConvertTextKey("TXT_KEY_TP_TURN_COUNTER", Game.GetGameTurn());
		Controls.CurrentTurn:SetText(turn);
		
		-- Update Unit Supply
		local iUnitSupplyMod = pPlayer:GetUnitProductionMaintenanceMod();
		if (iUnitSupplyMod ~= 0) then
			local iUnitsSupplied = pPlayer:GetNumUnitsSupplied();
			local iUnitsOver = pPlayer:GetNumUnitsOutOfSupply();
			local strUnitSupplyToolTip = Locale.ConvertTextKey("TXT_KEY_UNIT_SUPPLY_REACHED_TOOLTIP", iUnitsSupplied, iUnitsOver, -iUnitSupplyMod);
			
			Controls.UnitSupplyString:SetToolTipString(strUnitSupplyToolTip);
			Controls.UnitSupplyString:SetHide(false);
		else
			Controls.UnitSupplyString:SetHide(true);
		end
		
		-- Update date
		local year = Game.GetGameTurnYear();
		local date;
		if(year < 0) then
			date = Locale.ConvertTextKey("TXT_KEY_TIME_BC", math.abs(year));
		else
			date = Locale.ConvertTextKey("TXT_KEY_TIME_AD", math.abs(year));
		end
		
		Controls.CurrentDate:SetText(date);
	end
end

function OnTopPanelDirty()
	UpdateData();
end

-------------------------------------------------
-------------------------------------------------
function OnCivilopedia()	
	-- In City View, return to main game
	--if (UI.GetHeadSelectedCity() ~= nil) then
		--Events.SerialEventExitCityScreen();
	--end
	--
	-- opens the Civilopedia without changing its current state
	Events.SearchForPediaEntry();
end
Controls.CivilopediaButton:RegisterCallback( Mouse.eLClick, OnCivilopedia );


-------------------------------------------------
-------------------------------------------------
function OnMenu()
	
	-- In City View, return to main game
	if (UI.GetHeadSelectedCity() ~= nil) then
		Events.SerialEventExitCityScreen();
		--UI.SetInterfaceMode(InterfaceModeTypes.INTERFACEMODE_SELECTION);
	-- In Main View, open Menu Popup
	else
	    UIManager:QueuePopup( LookUpControl( "/InGame/GameMenu" ), PopupPriority.InGameMenu );
	end
end
Controls.MenuButton:RegisterCallback( Mouse.eLClick, OnMenu );


-------------------------------------------------
-------------------------------------------------
function OnCultureClicked()
	
	Events.SerialEventGameMessagePopup( { Type = ButtonPopupTypes.BUTTONPOPUP_CHOOSEPOLICY } );

end
Controls.CultureString:RegisterCallback( Mouse.eLClick, OnCultureClicked );


-------------------------------------------------
-------------------------------------------------
function OnTechClicked()
	
	Events.SerialEventGameMessagePopup( { Type = ButtonPopupTypes.BUTTONPOPUP_TECH_TREE } );

end
Controls.SciencePerTurn:RegisterCallback( Mouse.eLClick, OnTechClicked );


-------------------------------------------------
-- TOOLTIPS
-------------------------------------------------


-- Tooltip init
function DoInitTooltips()
	Controls.SciencePerTurn:SetToolTipCallback( ScienceTipHandler );
	Controls.GoldPerTurn:SetToolTipCallback( GoldTipHandler );
	Controls.HappinessString:SetToolTipCallback( HappinessTipHandler );
	Controls.GoldenAgeString:SetToolTipCallback( GoldenAgeTipHandler );
	Controls.CultureString:SetToolTipCallback( CultureTipHandler );
	Controls.GreatPeopleString:SetToolTipCallback(GreatPeopleTipHandler);
	Controls.ResourceString:SetToolTipCallback( ResourcesTipHandler );
end

-- Science Tooltip
local tipControlTable = {};
TTManager:GetTypeControlTable( "TooltipTypeTopPanel", tipControlTable );
function ScienceTipHandler( control )

	local strText = "";
	local iPlayerID = Game.GetActivePlayer();
	local pPlayer = Players[iPlayerID];
	local pTeam = Teams[pPlayer:GetTeam()];
	local pCity = UI.GetHeadSelectedCity();
	
	local iSciencePerTurn = pPlayer:GetScience();
	
	-- Science
	if (not OptionsManager.IsNoBasicHelp()) then
		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_SCIENCE", iSciencePerTurn);
		
		if (pPlayer:GetNumCities() > 0) then
			strText = strText .. "[NEWLINE][NEWLINE]";
		end
	end
	
	local bFirstEntry = true;
	
	-- Science LOSS from Budget Deficits
	local iScienceFromBudgetDeficit = pPlayer:GetScienceFromBudgetDeficitTimes100();
	if (iScienceFromBudgetDeficit ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			bFirstEntry = false;
		else
			strText = strText .. "[NEWLINE]";
		end

		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_SCIENCE_FROM_BUDGET_DEFICIT", iScienceFromBudgetDeficit / 100);
		strText = strText .. "[NEWLINE]";
	end
	
	-- Science from Cities
	local iScienceFromCities = pPlayer:GetScienceFromCitiesTimes100();
	if (iScienceFromCities ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			bFirstEntry = false;
		else
			strText = strText .. "[NEWLINE]";
		end

		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_SCIENCE_FROM_CITIES", iScienceFromCities / 100);
	end
	
	-- Science from Other Players
	local iScienceFromOtherPlayers = pPlayer:GetScienceFromOtherPlayersTimes100();
	if (iScienceFromOtherPlayers ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			bFirstEntry = false;
		else
			strText = strText .. "[NEWLINE]";
		end

		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_SCIENCE_FROM_MINORS", iScienceFromOtherPlayers / 100);
	end
	
	-- Science from Happiness
	local iScienceFromHappiness = pPlayer:GetScienceFromHappinessTimes100();
	if (iScienceFromHappiness ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			bFirstEntry = false;
		else
			strText = strText .. "[NEWLINE]";
		end

		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_SCIENCE_FROM_HAPPINESS", iScienceFromHappiness / 100);
	end
	
	-- Science from Research Agreements
	local iScienceFromRAs = pPlayer:GetScienceFromResearchAgreementsTimes100();
	if (iScienceFromRAs ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			bFirstEntry = false;
		else
			strText = strText .. "[NEWLINE]";
		end

		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_SCIENCE_FROM_RESEARCH_AGREEMENTS", iScienceFromRAs / 100);
	end
	
	tipControlTable.TooltipLabel:SetText( strText );
	tipControlTable.TopPanelMouseover:SetHide(false);
    
    -- Autosize tooltip
    tipControlTable.TopPanelMouseover:DoAutoSize();
	
end

-- Gold Tooltip
function GoldTipHandler( control )

	local strText = "";
	local iPlayerID = Game.GetActivePlayer();
	local pPlayer = Players[iPlayerID];
	local pTeam = Teams[pPlayer:GetTeam()];
	local pCity = UI.GetHeadSelectedCity();
	
	local iTotalGold = pPlayer:GetGold();

	local iGoldPerTurnFromOtherPlayers = pPlayer:GetGoldPerTurnFromDiplomacy();
	local iGoldPerTurnToOtherPlayers = 0;
	if (iGoldPerTurnFromOtherPlayers < 0) then
		iGoldPerTurnToOtherPlayers = -iGoldPerTurnFromOtherPlayers;
		iGoldPerTurnFromOtherPlayers = 0;
	end

	local fGoldPerTurnFromCities = pPlayer:GetGoldFromCitiesTimes100() / 100;
	local fCityConnectionGold = pPlayer:GetCityConnectionGoldTimes100() / 100;
	local fTotalIncome = fGoldPerTurnFromCities + iGoldPerTurnFromOtherPlayers + fCityConnectionGold;
	
	if (not OptionsManager.IsNoBasicHelp()) then
		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_AVAILABLE_GOLD", iTotalGold);
		strText = strText .. "[NEWLINE][NEWLINE]";
	end
	
	strText = strText .. "[COLOR:150:255:150:255]";
	strText = strText .. "+" .. Locale.ConvertTextKey("TXT_KEY_TP_TOTAL_INCOME", math.floor(fTotalIncome));
	strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_CITY_OUTPUT", fGoldPerTurnFromCities);
	--strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. tostring(fGoldPerTurnFromCities) .. " from the output of all Cities.";
	strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_GOLD_FROM_TR", math.floor(fCityConnectionGold));
	--strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. tostring(math.floor(fCityConnectionGold)) .. " from trade routes formed by Cities connected to your Capital by Road.";
	if (iGoldPerTurnFromOtherPlayers > 0) then
		strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_GOLD_FROM_OTHERS", iGoldPerTurnFromOtherPlayers);
		--strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. tostring(iGoldPerTurnFromOtherPlayers) .. " from other Civilizations.";
	end
	strText = strText .. "[/COLOR]";
	
	local iUnitCost = pPlayer:CalculateUnitCost();
	local iUnitSupply = pPlayer:CalculateUnitSupply();
	local iBuildingMaintenance = pPlayer:GetBuildingGoldMaintenance();
	local iImprovementMaintenance = pPlayer:GetImprovementGoldMaintenance();
	local iTotalExpenses = iUnitCost + iUnitSupply + iBuildingMaintenance + iImprovementMaintenance + iGoldPerTurnToOtherPlayers;
	
	strText = strText .. "[NEWLINE]";
	strText = strText .. "[COLOR:255:150:150:255]";
	strText = strText .. "[NEWLINE]-" .. Locale.ConvertTextKey("TXT_KEY_TP_TOTAL_EXPENSES", iTotalExpenses);
	--strText = strText .. "[NEWLINE]-" .. tostring(iTotalExpenses) .. " in total expenses.";
	if (iUnitCost ~= 0) then
		strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_UNIT_MAINT", iUnitCost);
		--strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. tostring(iUnitCost) .. " spent on Unit Maintenance.";
	end
	if (iUnitSupply ~= 0) then
		strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_GOLD_UNIT_SUPPLY", iUnitSupply);
		--strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. tostring(iUnitSupply) .. " spent on supplying Units outside your territory.";
	end
	if (iBuildingMaintenance ~= 0) then
		strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_GOLD_BUILDING_MAINT", iBuildingMaintenance);
		--strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. tostring(iBuildingMaintenance) .. " spent on Building Maintenance.";
	end
	if (iImprovementMaintenance ~= 0) then
		strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_GOLD_TILE_MAINT", iImprovementMaintenance);
		--strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. tostring(iImprovementMaintenance) .. " spent on Tile Improvement Maintenance.";
	end
	if (iGoldPerTurnToOtherPlayers > 0) then
		strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_GOLD_TO_OTHERS", iGoldPerTurnToOtherPlayers);
		--strText = strText .. "[NEWLINE]  [ICON_BULLET]" .. tostring(iGoldPerTurnToOtherPlayers) .. " to other Civilizations.";
	end
	strText = strText .. "[/COLOR]";
	
	if (fTotalIncome + iTotalGold < 0) then
		strText = strText .. "[NEWLINE][COLOR:255:60:60:255]" .. Locale.ConvertTextKey("TXT_KEY_TP_LOSING_SCIENCE_FROM_DEFICIT") .. "[/COLOR]";
		--strText = strText .. "[NEWLINE][COLOR:255:60:60:255]Expenses that can't be paid for will be taken out of your Science Rate![/COLOR]";
	end
	
	-- Basic explanation of Happiness
	if (not OptionsManager.IsNoBasicHelp()) then
		strText = strText .. "[NEWLINE][NEWLINE]";
		strText = strText ..  Locale.ConvertTextKey("TXT_KEY_TP_GOLD_EXPLANATION");
	end
	
	--Controls.GoldPerTurn:SetToolTipString(strText);
	
	tipControlTable.TooltipLabel:SetText( strText );
	tipControlTable.TopPanelMouseover:SetHide(false);
    
    -- Autosize tooltip
    tipControlTable.TopPanelMouseover:DoAutoSize();
	
end

-- Happiness Tooltip
function HappinessTipHandler( control )

	local strText;
	local iPlayerID = Game.GetActivePlayer();
	local pPlayer = Players[iPlayerID];
	local pTeam = Teams[pPlayer:GetTeam()];
	local pCity = UI.GetHeadSelectedCity();
	
	local iHappiness = pPlayer:GetExcessHappiness();

	if (not pPlayer:IsEmpireUnhappy()) then
		strText = Locale.ConvertTextKey("TXT_KEY_TP_TOTAL_HAPPINESS", iHappiness);
		--strText = "Total [ICON_HAPPINESS_1] Happiness Level of the empire is " .. tostring(iHappiness) .. ".";
	elseif (pPlayer:IsEmpireVeryUnhappy()) then
		strText = Locale.ConvertTextKey("TXT_KEY_TP_TOTAL_UNHAPPINESS", "[ICON_HAPPINESS_4]", -iHappiness);
		--strText = "Total [ICON_HAPPINESS_4] Unhappiness Level of the empire is " .. tostring(-iHappiness) .. ".";
	else
		strText = Locale.ConvertTextKey("TXT_KEY_TP_TOTAL_UNHAPPINESS", "[ICON_HAPPINESS_3]", -iHappiness);
		--strText = "Total [ICON_HAPPINESS_3] Unhappiness Level of the empire is " .. tostring(-iHappiness) .. ".";
	end
	
	local iPoliciesHappiness = pPlayer:GetHappinessFromPolicies();
	local iResourcesHappiness = pPlayer:GetHappinessFromResources();
	local iExtraLuxuryHappiness = pPlayer:GetExtraHappinessPerLuxury();
	local iBuildingHappiness = pPlayer:GetHappinessFromBuildings();
	local iGarrisonedUnitsHappiness = pPlayer:GetHappinessFromGarrisonedUnits();
	local iTradeRouteHappiness = pPlayer:GetHappinessFromTradeRoutes();
	local iReligionHappiness = pPlayer:GetHappinessFromReligion();
	local iNaturalWonderHappiness = pPlayer:GetHappinessFromNaturalWonders();
	local iExtraHappinessPerCity = pPlayer:GetExtraHappinessPerCity() * pPlayer:GetNumCities();
	
	local iMinorCivHappiness = 0;
	local pMinor;
	
	-- Loop through all the Minors the active player knows
	for iPlayerLoop = GameDefines.MAX_MAJOR_CIVS, GameDefines.MAX_CIV_PLAYERS-1, 1 do
		iMinorCivHappiness = iMinorCivHappiness + pPlayer:GetHappinessFromMinor(iPlayerLoop);
	end
	
	local iHandicapHappiness = pPlayer:GetHappiness() - iPoliciesHappiness - iResourcesHappiness - iBuildingHappiness - iGarrisonedUnitsHappiness - iTradeRouteHappiness - iReligionHappiness - iNaturalWonderHappiness - iMinorCivHappiness - iExtraHappinessPerCity;
	
	if (pPlayer:IsEmpireVeryUnhappy()) then
		strText = strText .. "[NEWLINE][NEWLINE]";
		strText = strText .. "[COLOR:255:60:60:255]" .. Locale.ConvertTextKey("TXT_KEY_TP_EMPIRE_VERY_UNHAPPY") .. "[/COLOR]";
		--strText = strText .. "[COLOR:255:60:60:255]Empire is [ICON_HAPPINESS_4] VERY unhappy! Production is greatly slowed and Units are less effective in combat![/COLOR]";
	elseif (pPlayer:IsEmpireUnhappy()) then
		
		strText = strText .. "[NEWLINE][NEWLINE]";
		strText = strText .. "[COLOR:255:60:60:255]" .. Locale.ConvertTextKey("TXT_KEY_TP_EMPIRE_UNHAPPY") .. "[/COLOR]";
		--strText = strText .. "[COLOR:255:60:60:255]Cities will only grow at 1/3 normal speed while empire is [ICON_HAPPINESS_3] unhappy![/COLOR]";
	end
	
	local iTotalHappiness = iPoliciesHappiness + iResourcesHappiness + iBuildingHappiness + iMinorCivHappiness + iHandicapHappiness + iTradeRouteHappiness + iReligionHappiness + iNaturalWonderHappiness + iExtraHappinessPerCity;
	
	strText = strText .. "[NEWLINE][NEWLINE]";
	strText = strText .. "[COLOR:150:255:150:255]";
	strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_SOURCES", iTotalHappiness);
	--strText = strText .. tostring(iTotalHappiness) .. " total [ICON_HAPPINESS_1] Happiness from all sources.[NEWLINE]";
	
	strText = strText .. "[NEWLINE]";
	strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_FROM_RESOURCES", iResourcesHappiness);
	--strText = strText .. "  [ICON_BULLET]" .. tostring(iResourcesHappiness) .. " from Resources.[NEWLINE]";
	
	-- Individual Resource Info

	local iBaseHappinessFromResources = 0;
	local iNumHappinessResources = 0;

	for resource in GameInfo.Resources() do
		local resourceID = resource.ID;
		if (pPlayer:GetNumResourceTotal(resourceID, true) > 0) then
			if (resource.Happiness ~= 0) then
				strText = strText .. "[NEWLINE]";
				strText = strText .. "          +" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_EACH_RESOURCE", resource.Happiness, resource.IconString, resource.Description);
				--strText = strText .. "          +" .. tostring(resource.Happiness) .. " from " .. resource.IconString .. "[NEWLINE]";
				iNumHappinessResources = iNumHappinessResources + 1;
				iBaseHappinessFromResources = iBaseHappinessFromResources + resource.Happiness;
			end
		end
	end
	
	-- Happiness from Luxury Variety
	local iHappinessFromExtraResources = pPlayer:GetHappinessFromResourceVariety();
	if (iHappinessFromExtraResources > 0) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "          +" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_RESOURCE_VARIETY", iHappinessFromExtraResources);
		--strText = strText .. "          +" .. tostring(iHappinessFromExtraResources) .. " for having a variety of Luxury Resources.[NEWLINE]";
	end
	
	-- Extra Happiness from each Luxury
	if (iExtraLuxuryHappiness >= 1) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "          +" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_EXTRA_PER_RESOURCE", iExtraLuxuryHappiness, iNumHappinessResources);
		--strText = strText .. "          +" .. tostring(iExtraLuxuryHappiness) .. " extra Happiness per Luxury Resource (" .. tostring(iNumHappinessResources) .. ").[NEWLINE]";
	end
	
	-- Misc Happiness from Resources
	local iMiscHappiness = iResourcesHappiness - iBaseHappinessFromResources - iHappinessFromExtraResources - (iExtraLuxuryHappiness * iNumHappinessResources);
	if (iMiscHappiness > 0) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "          +" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_OTHER_SOURCES", iMiscHappiness);
		--strText = strText .. "          +" .. tostring(iMiscHappiness) .. " from other sources.[NEWLINE]";
	end
	
	strText = strText .. "[NEWLINE]";
	strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_POLICIES", iPoliciesHappiness);
	--strText = strText .. "  [ICON_BULLET]" .. tostring(iPoliciesHappiness) .. " from Social Policies.[NEWLINE]";
	strText = strText .. "[NEWLINE]";
	strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_BUILDINGS", iBuildingHappiness);
	--strText = strText .. "  [ICON_BULLET]" .. tostring(iBuildingHappiness) .. " from Buildings.[NEWLINE]";
	if (iGarrisonedUnitsHappiness ~= 0) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_GARRISONED_UNITS", iGarrisonedUnitsHappiness);
		--strText = strText .. "  [ICON_BULLET]" .. tostring(iGarrisonedUnitsHappiness) .. " from Garrisoned Units.[NEWLINE]";
	end
	if (iTradeRouteHappiness ~= 0) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_CONNECTED_CITIES", iTradeRouteHappiness);
		--strText = strText .. "  [ICON_BULLET]" .. tostring(iTradeRouteHappiness) .. " from Cities connected to Capital.[NEWLINE]";
	end
	if (iReligionHappiness ~= 0) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_STATE_RELIGION", iReligionHappiness);
		--strText = strText .. "  [ICON_BULLET]" .. tostring(iReligionHappiness) .. " from presence of State Religion in our Cities.[NEWLINE]";
	end
	if (iNaturalWonderHappiness ~= 0) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_NATURAL_WONDERS", iNaturalWonderHappiness);
	end
	if (iExtraHappinessPerCity ~= 0) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_CITY_COUNT", iExtraHappinessPerCity);
		--strText = strText .. "  [ICON_BULLET]" .. tostring(iExtraHappinessPerCity) .. " from number of Cities.[NEWLINE]";
	end
	if (iMinorCivHappiness ~= 0) then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_CITY_STATE_FRIENDSHIP", iMinorCivHappiness);
		--strText = strText .. "  [ICON_BULLET]" .. tostring(iMinorCivHappiness) .. " from friendship with City States.[NEWLINE]";
	end
	strText = strText .. "[NEWLINE]";
	strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_DIFFICULTY_LEVEL", iHandicapHappiness);
	--strText = strText .. "  [ICON_BULLET]" .. tostring(iHandicapHappiness) .. " from Difficulty Level.[NEWLINE]";
	strText = strText .. "[/COLOR]";
	
	local iTotalUnhappiness = pPlayer:GetUnhappiness();
	local iUnhappinessFromUnits = Locale.ToNumber( pPlayer:GetUnhappinessFromUnits() / 100, "#.##" );
	local iUnhappinessFromCityCount = Locale.ToNumber( pPlayer:GetUnhappinessFromCityCount() / 100, "#.##" );
	local iUnhappinessFromCapturedCityCount = Locale.ToNumber( pPlayer:GetUnhappinessFromCapturedCityCount() / 100, "#.##" );
	local iUnhappinessFromPop = Locale.ToNumber( pPlayer:GetUnhappinessFromCityPopulation() / 100, "#.##" );
	local iUnhappinessFromOccupiedCities = Locale.ToNumber( pPlayer:GetUnhappinessFromOccupiedCities() / 100, "#.##" );

	strText = strText .. "[NEWLINE][NEWLINE]";
	strText = strText .. "[COLOR:255:150:150:255]";
	strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_UNHAPPINESS_TOTAL", iTotalUnhappiness);
	--strText = strText .. tostring(iTotalUnhappiness) .. " total [ICON_HAPPINESS_4] Unhappiness from all sources.[NEWLINE]";
	strText = strText .. "[NEWLINE]";
	strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_UNHAPPINESS_CITY_COUNT", iUnhappinessFromCityCount);
	--strText = strText .. "  [ICON_BULLET]" .. tostring(iUnhappinessFromCityCount) .. " generated from number of settled Cities in the empire.[NEWLINE]";
	if (iUnhappinessFromCapturedCityCount ~= "0") then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_UNHAPPINESS_CAPTURED_CITY_COUNT", iUnhappinessFromCapturedCityCount);
		--strText = strText .. "  [ICON_BULLET]" .. tostring(iUnhappinessFromCapturedCityCount) .. " from number of captured Cities (including Puppets).[NEWLINE]";
	end
	strText = strText .. "[NEWLINE]";
	strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_UNHAPPINESS_POPULATION", iUnhappinessFromPop);
	--strText = strText .. "  [ICON_BULLET]" .. tostring(iUnhappinessFromPop) .. " generated by Population.[NEWLINE]";
	if (iUnhappinessFromOccupiedCities ~= "0") then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_UNHAPPINESS_OCCUPIED_POPULATION", iUnhappinessFromOccupiedCities);
		--strText = strText .. "  [ICON_BULLET]" .. tostring(iUnhappinessFromOccupiedCities) .. " from Population in Occupied Cities.[NEWLINE]";
	end
	if (iUnhappinessFromUnits ~= "0") then
		strText = strText .. "[NEWLINE]";
		strText = strText .. "  [ICON_BULLET]" .. Locale.ConvertTextKey("TXT_KEY_TP_UNHAPPINESS_UNITS", iUnhappinessFromUnits);
		--strText = strText .. "  [ICON_BULLET]" .. tostring(iUnhappinessFromUnits) .. " generated by Units.";
	end
	strText = strText .. "[/COLOR]";
	
	-- Basic explanation of Happiness
	if (not OptionsManager.IsNoBasicHelp()) then
		strText = strText .. "[NEWLINE][NEWLINE]";
		strText = strText ..  Locale.ConvertTextKey("TXT_KEY_TP_HAPPINESS_EXPLANATION");
	end
	
	tipControlTable.TooltipLabel:SetText( strText );
	tipControlTable.TopPanelMouseover:SetHide(false);
    
    -- Autosize tooltip
    tipControlTable.TopPanelMouseover:DoAutoSize();
	
end

-- Golden Age Tooltip
function GoldenAgeTipHandler( control )

	local strText;
	local iPlayerID = Game.GetActivePlayer();
	local pPlayer = Players[iPlayerID];
	local pTeam = Teams[pPlayer:GetTeam()];
	local pCity = UI.GetHeadSelectedCity();
	
	if (pPlayer:GetGoldenAgeTurns() > 0) then
		strText = Locale.ConvertTextKey("TXT_KEY_TP_GOLDEN_AGE_NOW", pPlayer:GetGoldenAgeTurns());
		--strText = string.format("The empire is in a [ICON_GOLDEN_AGE] GOLDEN AGE for %i more turns!", pPlayer:GetGoldenAgeTurns());
	else
		local iHappiness = pPlayer:GetExcessHappiness();

		strText = Locale.ConvertTextKey("TXT_KEY_TP_GOLDEN_AGE_PROGRESS", pPlayer:GetGoldenAgeProgressMeter(), pPlayer:GetGoldenAgeProgressThreshold());
		strText = strText .. "[NEWLINE]";
		
		if (iHappiness >= 0) then
			strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_GOLDEN_AGE_ADDITION", iHappiness);
		else
			strText = strText .. "[COLOR_WARNING_TEXT]" .. Locale.ConvertTextKey("TXT_KEY_TP_GOLDEN_AGE_LOSS", -iHappiness) .. "[ENDCOLOR]";
		end
		
		--strText = string.format("%i/%i progress towards the next [ICON_GOLDEN_AGE] Golden Age. +%i is added per turn from excess [ICON_HAPPINESS_1] Happiness.", pPlayer:GetGoldenAgeProgressMeter(), pPlayer:GetGoldenAgeProgressThreshold(), iHappiness);
	end
	
	strText = strText .. "[NEWLINE][NEWLINE]";
	strText = strText ..  Locale.ConvertTextKey("TXT_KEY_TP_GOLDEN_AGE_EFFECT");
	--strText = strText .. "[NEWLINE][NEWLINE]While in a [ICON_GOLDEN_AGE] Golden Age, every tile in your empire that produces at least 1 [ICON_PRODUCTION]Production or[ICON_GOLD]Gold gets 1 extra.";
	
	tipControlTable.TooltipLabel:SetText( strText );
	tipControlTable.TopPanelMouseover:SetHide(false);
    
    -- Autosize tooltip
    tipControlTable.TopPanelMouseover:DoAutoSize();
	
end

-- Culture Tooltip
function CultureTipHandler( control )

	local strText = "";
	local iPlayerID = Game.GetActivePlayer();
	local pPlayer = Players[iPlayerID];
    
    local iTurns;
    local iCultureNeeded = pPlayer:GetNextPolicyCost() - pPlayer:GetJONSCulture();
    if (iCultureNeeded <= 0) then
		iTurns = 0;
    else
		if (pPlayer:GetTotalJONSCulturePerTurn() == 0) then
			iTurns = "?";
		else
			iTurns = iCultureNeeded / pPlayer:GetTotalJONSCulturePerTurn();
			iTurns = iTurns + 1;
			iTurns = math.floor(iTurns);
		end
    end
    strText = strText .. Locale.ConvertTextKey("TXT_KEY_NEXT_POLICY_TURN_LABEL", iTurns);
	
	if (not OptionsManager.IsNoBasicHelp()) then
		strText = strText .. "[NEWLINE][NEWLINE]";
		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_CULTURE_ACCUMULATED", pPlayer:GetJONSCulture());
		strText = strText .. "[NEWLINE]";
		
		if (pPlayer:GetNextPolicyCost() > 0) then
			strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_CULTURE_NEXT_POLICY", pPlayer:GetNextPolicyCost());
		end
	end

	local bFirstEntry = true;
	
	-- Culture for Free
	local iCultureForFree = pPlayer:GetJONSCulturePerTurnForFree();
	if (iCultureForFree ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			strText = strText .. "[NEWLINE]";
			bFirstEntry = false;
		end

		strText = strText .. "[NEWLINE]";
		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_CULTURE_FOR_FREE", iCultureForFree);
	end
	
	-- Culture from Cities
	local iCultureFromCities = pPlayer:GetJONSCulturePerTurnFromCities();
	if (iCultureFromCities ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			strText = strText .. "[NEWLINE]";
			bFirstEntry = false;
		end

		strText = strText .. "[NEWLINE]";
		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_CULTURE_FROM_CITIES", iCultureFromCities);
	end
	
	-- Culture from Excess Happiness
	local iCultureFromHappiness = pPlayer:GetJONSCulturePerTurnFromExcessHappiness();
	if (iCultureFromHappiness ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			strText = strText .. "[NEWLINE]";
			bFirstEntry = false;
		end

		strText = strText .. "[NEWLINE]";
		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_CULTURE_FROM_HAPPINESS", iCultureFromHappiness);
	end
	
	-- Culture from Minor Civs
	local iCultureFromMinors = pPlayer:GetJONSCulturePerTurnFromMinorCivs();
	if (iCultureFromMinors ~= 0) then
		
		-- Add separator for non-initial entries
		if (bFirstEntry) then
			strText = strText .. "[NEWLINE]";
			bFirstEntry = false;
		end

		strText = strText .. "[NEWLINE]";
		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_CULTURE_FROM_MINORS", iCultureFromMinors);
	end
	
	-- Let people know that building more cities makes policies harder to get
	if (not OptionsManager.IsNoBasicHelp()) then
		strText = strText .. "[NEWLINE][NEWLINE]";
		strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_CULTURE_CITY_COST", Game.GetNumCitiesPolicyCostMod());
	end
	
	tipControlTable.TooltipLabel:SetText( strText );
	tipControlTable.TopPanelMouseover:SetHide(false);
    
    -- Autosize tooltip
    tipControlTable.TopPanelMouseover:DoAutoSize();
	
end

---------------------------------------------------
---------ADDED Update Great People Tooltip---------
---------------------------------------------------

function GreatPeopleTipHandler( control )
	local pPlayer = Players[ Game.GetActivePlayer() ];
	local strGreatPeopleStr = "";
	local GPList = listProgress(pPlayer);

	Controls.GreatPeopleString:SetHide(false);
				
	--Find city/GP closest to finish.
	local maxKey;
	local min = math.huge;
	for k,v in pairs(GPList) do
		local threshold = k[1]:GetSpecialistUpgradeThreshold();
		if(threshold-v < min) then
			min = threshold-v;
			maxKey = k;
		end
	end

	----------------------------------------------
	--set variables
	----------------------------------------------
	local theCity = maxKey[1];

	local pSpecialistInfo = maxKey[2];

	local cityName = Locale.ToUpper(Locale.ConvertTextKey(theCity:GetNameKey()));
		local prettyCityName = string.sub(cityName, 1, 1) .. string.lower(string.sub(cityName, 2));

	local GPName = getGPName(pSpecialistInfo);

	local threshold = theCity:GetSpecialistUpgradeThreshold();
	----------------------------------------------
	----------------------------------------------
			
	
	--set rate of change			
	local rateOfChange = 0;
	-----------------------
	rateOfChange = getRateOfChange(theCity, pSpecialistInfo, pPlayer)
	-----------------------


	--set number of turns until production
	local numTurns = "";
	-----------------------
	if(rateOfChange == 0) then
		numTurns = "infinity";
	else
		numTurns = math.floor((((threshold - GPList[maxKey])/rateOfChange)+1));
	end
	-----------------------



	strGreatPeopleStr = strGreatPeopleStr .. "[COLOR:241:202:25:255]Next Great Person:[NEWLINE] [ICON_BULLET][ICON_GREAT_PEOPLE] " .. GPName .. " from " .. prettyCityName .. " in " .. numTurns .. " turn(s).[/COLOR]";


	--Delete the GP closest to production (we don't need to show it again, nor do we need to show another production of the same GP type)
	for k,v in pairs(GPList) do
		if(k[2] == pSpecialistInfo) then
			GPList[k] = nil;
		end
	end

	-----------------------------
	-- Get closest to production for remaining GP types (should be 3)
	-----------------------------
	
	--get list of remaining GP types
	greatPeopleList = {};
	for specialistInfo in GameInfo.Specialists() do
		if (tostring(specialistInfo.GreatPeopleUnitClass) ~= "nil") then
			if(specialistInfo ~= pSpecialistInfo) then
				table.insert(greatPeopleList, specialistInfo);
			end
		end
	end


	--get closest city/GP pair to production for each GP type. (maxKey1 pertains to the 1st GP type in greatPeopleList and so on and so forth)
	---------------------------------------------------
	---------------------------------------------------
	local maxKey1;
	local maxKey2;
	local maxKey3;
	local min1 = math.huge;
	local min2 = math.huge;
	local min3 = math.huge;
	for k,v in pairs(GPList) do
		local threshold = k[1]:GetSpecialistUpgradeThreshold();
		if(k[2] == greatPeopleList[1]) then
			print("1");
			if(threshold-v < min1) then
				min1 = threshold-v;
				maxKey1 = k;
			end
		elseif(k[2] == greatPeopleList[2]) then
			print("2");
			if(threshold-v < min2) then
				min2 = threshold-v;
				maxKey2 = k;
			end
		else	
			print("3");
			if(threshold-v < min3) then
				min3 = threshold-v;
				maxKey3 = k;
			end
		end
	end
	---------------------------------------------------
	---------------------------------------------------
	
	--convert into string
	if(maxKey1 ~= nil) then
		print("maxKey1 ~= nil");
		theCity = maxKey1[1];

		pSpecialistInfo = maxKey1[2];

		cityName = Locale.ToUpper(Locale.ConvertTextKey(theCity:GetNameKey()));
			prettyCityName = string.sub(cityName, 1, 1) .. string.lower(string.sub(cityName, 2));

		GPName = getGPName(pSpecialistInfo);

		threshold = theCity:GetSpecialistUpgradeThreshold();

		rateOfChange = 0;
		rateOfChange = getRateOfChange(theCity, pSpecialistInfo, pPlayer)

		local numTurns = "";
		if(rateOfChange == 0) then
			numTurns = "infinity";
		elseif(rateOfChange > 0) then
			numTurns = math.floor((((threshold - GPList[maxKey1])/rateOfChange)+1));
		end

		strGreatPeopleStr = strGreatPeopleStr .. "[NEWLINE][NEWLINE]Progress towards next [ICON_GREAT_PEOPLE] "..GPName.. ": " .. GPList[maxKey1] .. "/" .. threshold ..
			"[NEWLINE](+"..rateOfChange.."[ICON_GREAT_PEOPLE]) ("..numTurns.." Turn(s)) ("..prettyCityName..")";
	end

	--convert into string
	if(maxKey2 ~= nil) then
		print("maxKey2 ~= nil");
		theCity = maxKey2[1];

		pSpecialistInfo = maxKey2[2];

		cityName = Locale.ToUpper(Locale.ConvertTextKey(theCity:GetNameKey()));
			prettyCityName = string.sub(cityName, 1, 1) .. string.lower(string.sub(cityName, 2));

		GPName = getGPName(pSpecialistInfo);

		threshold = theCity:GetSpecialistUpgradeThreshold();

		rateOfChange = 0;
		rateOfChange = getRateOfChange(theCity, pSpecialistInfo, pPlayer)

		local numTurns = "";
		if(rateOfChange == 0) then
			numTurns = "infinity";
		elseif(rateOfChange > 0) then
			numTurns = math.floor((((threshold - GPList[maxKey2])/rateOfChange)+1));
		end

		strGreatPeopleStr = strGreatPeopleStr .. "[NEWLINE][NEWLINE]Progress towards next [ICON_GREAT_PEOPLE] "..GPName.. ": " .. GPList[maxKey2] .. "/" .. threshold ..
			"[NEWLINE](+"..rateOfChange.."[ICON_GREAT_PEOPLE]) ("..numTurns.." Turn(s)) ("..prettyCityName..")";
	end
	
	--convert into string
	if(maxKey3~=nil) then
		print("maxKey3 ~= nil");
		theCity = maxKey3[1];

		pSpecialistInfo = maxKey3[2];

		cityName = Locale.ToUpper(Locale.ConvertTextKey(theCity:GetNameKey()));
			prettyCityName = string.sub(cityName, 1, 1) .. string.lower(string.sub(cityName, 2));

		GPName = getGPName(pSpecialistInfo);

		threshold = theCity:GetSpecialistUpgradeThreshold();

		rateOfChange = 0;
		rateOfChange = getRateOfChange(theCity, pSpecialistInfo, pPlayer)

		local numTurns = "";
		if(rateOfChange == 0) then
			numTurns = "infinity";
		elseif(rateOfChange > 0) then
			numTurns = math.floor((((threshold - GPList[maxKey3])/rateOfChange)+1));
		end

		strGreatPeopleStr = strGreatPeopleStr .. "[NEWLINE][NEWLINE]Progress towards next [ICON_GREAT_PEOPLE] "..GPName.. ": " .. GPList[maxKey3] .. "/" .. threshold ..
		"[NEWLINE](+"..rateOfChange.."[ICON_GREAT_PEOPLE]) ("..numTurns.." Turn(s)) ("..prettyCityName..")";	
	end				

	--add great general at the end
	local fProgress  = pPlayer:GetCombatExperience();
	local fThreshold = pPlayer:GreatGeneralThreshold();
	if(fProgress > 0) then
		strGreatPeopleStr = strGreatPeopleStr .. "[NEWLINE][NEWLINE] Progress towards next [ICON_GREAT_PEOPLE] Great General: " .. fProgress .. "/" .. fThreshold;
	end

	--strGreatPeopleStr = strGreatPeopleStr .. "[/COLOR]";
	tipControlTable.TooltipLabel:SetText( strGreatPeopleStr );
	tipControlTable.TopPanelMouseover:SetHide(false);
    -- Autosize tooltip
    tipControlTable.TopPanelMouseover:DoAutoSize();
end
---------------------------------------------------
----------------END ADD (finally)------------------
---------------------------------------------------



-- Resources Tooltip
function ResourcesTipHandler( control )

	local strText;
	local iPlayerID = Game.GetActivePlayer();
	local pPlayer = Players[iPlayerID];
	local pTeam = Teams[pPlayer:GetTeam()];
	local pCity = UI.GetHeadSelectedCity();
	
	strText = ""; --Locale.ConvertTextKey("TXT_KEY_TP_NO_RESOURCES_DISCOVERED");
	--strText = "No Resources discovered yet!";
	
	local pResource;
	local bShowResource;
	local bThisIsFirstResourceShown = true;
	local iNumAvailable;
	local iNumUsed;
	local iNumTotal;
	
	for pResource in GameInfo.Resources() do
		local iResourceLoop = pResource.ID;
		
		if (Game.GetResourceUsageType(iResourceLoop) == ResourceUsageTypes.RESOURCEUSAGE_STRATEGIC) then
			
			bShowResource = false;
			
			if (pTeam:GetTeamTechs():HasTech(GameInfoTypes[pResource.TechReveal])) then
				if (pTeam:GetTeamTechs():HasTech(GameInfoTypes[pResource.TechCityTrade])) then
					bShowResource = true;
				end
			end
			
			if (bShowResource) then
				iNumAvailable = pPlayer:GetNumResourceAvailable(iResourceLoop, true);
				iNumUsed = pPlayer:GetNumResourceUsed(iResourceLoop);
				iNumTotal = pPlayer:GetNumResourceTotal(iResourceLoop, true);
				
				-- Add newline to the front of all entries that AREN'T the first
				if (bThisIsFirstResourceShown) then
					strText = "";
					bThisIsFirstResourceShown = false;
				else
					strText = strText .. "[NEWLINE]";
				end
				
				strText = strText .. iNumAvailable .. " " .. pResource.IconString .. " " .. Locale.ConvertTextKey(pResource.Description);
				
				-- Details
				if (iNumUsed ~= 0 or iNumTotal ~= 0) then
					strText = strText .. ": ";
					strText = strText .. Locale.ConvertTextKey("TXT_KEY_TP_RESOURCE_INFO", iNumTotal, iNumUsed);
				end
				
				--strText = strText .. "[ICON_BULLET]" .. tostring(pPlayer:GetNumResourceAvailable(iResourceLoop, true)) .. " available, " .. tostring(iNumTotal) .. " total, " .. tostring(iNumUsed) .. " used.";
			end
		end
	end
	
	print(strText);
	if(strText ~= "") then
		tipControlTable.TopPanelMouseover:SetHide(false);
		tipControlTable.TooltipLabel:SetText( strText );
	else
		tipControlTable.TopPanelMouseover:SetHide(true);
	end
    
    -- Autosize tooltip
    tipControlTable.TopPanelMouseover:DoAutoSize();
	
end

-------------------------------------------------
-- On Top Panel mouseover exited
-------------------------------------------------
--function HelpClose()
	---- Hide the help text box
	--Controls.HelpTextBox:SetHide( true );
--end


-- Register Events
Events.SerialEventGameDataDirty.Add(OnTopPanelDirty);
Events.SerialEventTurnTimerDirty.Add(OnTopPanelDirty);
Events.SerialEventCityInfoDirty.Add(OnTopPanelDirty);

-- Update data at initialization
UpdateData();
DoInitTooltips();

---------------------- SimpleClock.lua
-- Authors: Firaxis
-- This mod sample displays how to create a basic InGameUIAddin.
----------------------------------------------------------------  
ContextPtr:SetUpdate(function()
	local t = os.date("%I:%M");
	Controls.ClockLabel:SetString(t);
end);

-- LuxuryResourceDisplay.lua
-- Author: Magus
-- This mod displays Luxury Resources similar to the existing Strategic Resource display.
-------------------------------------------------------------------------------------------
-- include( "TradeLogic" );

-- print("Initializing...");

function DebugObject(o)
	for key,value in pairs(o) do
		if (value == true) then
			print(string.format("o.%s: %s", key, "true"));
		elseif (value == false) then
			print(string.format("o.%s: %s", key, "false"));
		elseif (type(value) == "string" or type(value) == "integer") then
			print(string.format("o.%s: %s", key, value));
		else
			print(string.format("o.%s: %s", key, "unknown"));
		end
	end
end

function TradedResources(iResourceID)
	local iPlayerID = Game.GetActivePlayer();
	local count = 0;

	if(iPlayerID >= 0) then
		local itemType;
		local duration;
		local finalTurn;
		local data1;
		local data2;
		local fromPlayer;

		local m_Deal = UI.GetScratchDeal();
		local iNumCurrentDeals = UI:GetNumCurrentDeals( iPlayer );

		if( iNumCurrentDeals > 0 ) then
			for i = 0, iNumCurrentDeals - 1 do
				UI.LoadCurrentDeal( iPlayerID, i );
				
				m_Deal:ResetIterator();
				itemType, duration, finalTurn, data1, data2, fromPlayer = m_Deal:GetNextItem();
				repeat
					if (data1 == iResourceID) then
						if (fromPlayer == iPlayerID) then
							count = count - 1;
						else
							count = count + 1;
						end
					end
					itemType, duration, finalTurn, data1, data2, fromPlayer = m_Deal:GetNextItem();
				until (itemType == nil);
			end
		end
	end
	return count;
end

function UpdateLuxuryResourceDisplay()
	local iPlayerID = Game.GetActivePlayer();

	if(iPlayerID >= 0) then
		local pPlayer = Players[iPlayerID];

		if (pPlayer:GetNumCities() > 0) then
			-----------------------------
			-- Update Resources
			-----------------------------
			local pResource;
			local iNumAvailable;
			local iNumUsed;
			local iNumTotal;

			local iTotal = 0;

			for pResource in GameInfo.Resources() do
				local iResourceLoop = pResource.ID;
				local bLuxury = (Game.GetResourceUsageType(iResourceLoop) == ResourceUsageTypes.RESOURCEUSAGE_LUXURY);

				if (bLuxury) then

					iNumAvailable = pPlayer:GetNumResourceAvailable(iResourceLoop, true);
					-- iNumUsed = pPlayer:GetNumResourceUsed(iResourceLoop);
					-- iNumTotal = pPlayer:GetNumResourceTotal(iResourceLoop, true);

					if (iNumAvailable > 0) then
						iTotal = iTotal + 1;
					end
				end
			end

			Controls.LuxuryResourceString:SetText(string.format("%i Luxuries", iTotal));
		end
	end
end


-------------------------------------------------
-- TOOLTIPS
-------------------------------------------------


-- Tooltip init
function DoInitTooltipsLR()
	Controls.LuxuryResourceString:SetToolTipCallback(LuxuryResourcesTipHandler);
end

local tipControlTable = {};
TTManager:GetTypeControlTable("TooltipTypeTopPanel", tipControlTable);

-- Resources Tooltip
function LuxuryResourcesTipHandler(control)
	local strText;
	local strExtraText;
	local iPlayerID = Game.GetActivePlayer();
	local pPlayer = Players[iPlayerID];

	local pResource;
	local iNumAvailable;
	local iNumUsed;
	local iNumTotal;

	local tKeys = {};
	local tResources = {};

	for pResource in GameInfo.Resources() do
		local iResourceLoop = pResource.ID;
		local bLuxury = (Game.GetResourceUsageType(iResourceLoop) == ResourceUsageTypes.RESOURCEUSAGE_LUXURY);

		if (bLuxury) then
			iNumAvailable = pPlayer:GetNumResourceAvailable(iResourceLoop, true);
			iTradeCount = TradedResources(iResourceLoop);					

			-- how many total?
			if(iTradeCount < 0) then
				iNumTotal  = iNumAvailable - iTradeCount;
			else
				iNumTotal = iNumAvailable;
			end

			-- display it if we have it
			if(iNumTotal > 0) then
				strText = "";
				strExtraText = "";
				strText = strText .. iNumAvailable .. " ";
				strText = strText .. string.format("%s %s", pResource.IconString, Locale.ConvertTextKey(pResource.Description));

				if (iTradeCount > 0) then
					strExtraText = ": ";
					strExtraText = strExtraText .. string.format("[COLOR_POSITIVE_TEXT]%i Imported[ENDCOLOR]", iTradeCount);
				elseif (iTradeCount < 0) then
					strExtraText = ": ";
					strExtraText = strExtraText .. string.format("[COLOR_WARNING_TEXT]%i Exported[ENDCOLOR]", -1 * iTradeCount);
				end

				strText = strText .. strExtraText;

				table.insert(tKeys, Locale.ConvertTextKey(pResource.Description));
				tResources[Locale.ConvertTextKey(pResource.Description)] = strText;
			end
		end
	end

	table.sort(tKeys);

	strText = "";
	for i,k in ipairs(tKeys) do
		if (i > 1) then
			strText = strText .. "[NEWLINE]";
		end
		strText = strText .. tResources[k];
	end

	-- print(strText);
	if(strText ~= "") then
		tipControlTable.TopPanelMouseover:SetHide(false);
		tipControlTable.TooltipLabel:SetText(strText);
	else
		tipControlTable.TopPanelMouseover:SetHide(true);
	end

    -- Autosize tooltip
    tipControlTable.TopPanelMouseover:DoAutoSize();

end

Events.SerialEventGameDataDirty.Add(UpdateLuxuryResourceDisplay);
Events.SerialEventTurnTimerDirty.Add(UpdateLuxuryResourceDisplay);
Events.SerialEventCityInfoDirty.Add(UpdateLuxuryResourceDisplay);

UpdateLuxuryResourceDisplay();
DoInitTooltipsLR();


