## RawYields
##
## Calculates the raw yields of food, production and commerce for a city
## and displays them in the trade table when enabled.
##
## Copyright (c) 2008 The BUG Mod.
##
## Author: EmperorFool

from CvPythonExtensions import *
import CvUtil
import BugUtil
import TradeUtil

gc = CyGlobalContext()

# Types
NUM_TYPES = 11
(
	WORKED_TILES,
	CITY_TILES,
	OWNED_TILES,
	ALL_TILES,
	
	DOMESTIC_TRADE,
	FOREIGN_TRADE, # excludes overseas trade
	
	BUILDINGS,
	CORPORATIONS,
	SPECIALISTS,
	
	# Hold the percents, not the actual yield values
	BASE_MODIFIER,
	PRODUCTION_MODIFIER,
) = range(NUM_TYPES)

# Leave these for later when we have icons for each
#DOMAIN_MODIFIER
#MILITARY_MODIFIER
#TRAIT_MODIFIER
#CIVIC_MODIFIER
#RELIGION_MODIFIER
#BONUS_MODIFIER
#WONDER_MODIFIER
#...

# Labels
LABEL_KEYS = ("TXT_KEY_CONCEPT_WORKED_TILES",
			  "TXT_KEY_CONCEPT_CITY_TILES",
			  "TXT_KEY_CONCEPT_OWNED_TILES",
			  "TXT_KEY_CONCEPT_ALL_TILES",
			  "TXT_KEY_CONCEPT_DOMESTIC_TRADE",
			  "TXT_KEY_CONCEPT_FOREIGN_TRADE",
			  "TXT_KEY_CONCEPT_BUILDINGS",
			  "TXT_KEY_CONCEPT_CORPORATIONS",
			  "TXT_KEY_CONCEPT_SPECIALISTS",
			  "TXT_KEY_CONCEPT_BASE_MODIFIER",
			  "TXT_KEY_CONCEPT_PRODUCTION_MODIFIER")

# Yields
YIELDS = (YieldTypes.YIELD_FOOD, YieldTypes.YIELD_PRODUCTION, YieldTypes.YIELD_COMMERCE)

# Tiles
TILES = (WORKED_TILES, CITY_TILES, OWNED_TILES, ALL_TILES)

# Table
HEADING_COLUMN = 0
VALUE_COLUMN = 1
TOTAL_COLUMN = 2

def getViewAndType(iView):
	"""Returns the view boolean and YieldTypes enum given the give number 0-3."""
	if iView == 0:
		return (False, YieldTypes.YIELD_FOOD)
	elif iView in (1, 2, 3):
		return (True, YIELDS[iView - 1])
	else:
		BugUtil.error("RawYields - invalid view number %d", iView)
		return (False, YieldTypes.YIELD_FOOD)

class Tracker:
	
	def __init__(self):
		"""Creates a table to hold all of the tracked values for each yield type."""
		self.values = {}
		for eYield in range(YieldTypes.NUM_YIELD_TYPES):
			self.values[eYield] = {}
			for eType in range(NUM_TYPES):
				self.values[eYield][eType] = 0
		self.tileCounts = [0, 0, 0, 0]
	
	
	def getYield(self, eYield, eType):
		return self.values[eYield][eType]
	
	def _addYield(self, eYield, eType, iValue):
		"""Adds the given yield value to the given type in the table."""
		self.values[eYield][eType] += iValue
	
	
	def addBuilding(self, eYield, iValue):
		self._addYield(eYield, BUILDINGS, iValue)
	
	def addDomesticTrade(self, iValue):
		self._addYield(YieldTypes.YIELD_COMMERCE, DOMESTIC_TRADE, iValue)
	
	def addForeignTrade(self, iValue):
		self._addYield(YieldTypes.YIELD_COMMERCE, FOREIGN_TRADE, iValue)
	
	def processCity(self, pCity):
		"""
		Calculates the yields for the given city's tiles, specialists, corporations and multipliers.
		The building and trade yields are calculated by CvMainInterface.
		"""
		self.calculateTiles(pCity)
		self.calculateSpecialists(pCity)
		self.calculateCorporations(pCity)
		self.calculateModifiers(pCity)
	
	def calculateTiles(self, pCity):
		"""Calculates the yields for all tiles of the given CyCity."""
		for i in range(gc.getNUM_CITY_PLOTS()):
			pPlot = pCity.getCityIndexPlot(i)
			if pPlot and not pPlot.isNone() and pPlot.hasYield():
				if pCity.isWorkingPlot(pPlot):
					self._addTile(WORKED_TILES, pPlot)
				elif pCity.canWork(pPlot):
					self._addTile(CITY_TILES, pPlot)
				elif pPlot.getOwner() == pCity.getOwner():
					self._addTile(OWNED_TILES, pPlot)
				else:
					self._addTile(ALL_TILES, pPlot)
	
	def _addTile(self, eFirstTileType, pPlot):
		for eYield in YIELDS:
			iValue = pPlot.getYield(eYield)
			for eType in range(eFirstTileType, ALL_TILES + 1):
				self._addYield(eYield, eType, iValue)
		for eType in range(eFirstTileType, ALL_TILES + 1):
			self.tileCounts[eType] += 1
	
	def calculateSpecialists(self, pCity):
		pPlayer = gc.getPlayer(pCity.getOwner())
		for eYield in range(YieldTypes.NUM_YIELD_TYPES):
			iValue = 0
			for eSpec in range(gc.getNumSpecialistInfos()):
				iValue += pPlayer.specialistYield(eSpec, eYield) * (pCity.getSpecialistCount(eSpec) + pCity.getFreeSpecialistCount(eSpec))
			self.addSpecialist(eYield, iValue)
	
	def addSpecialist(self, eYield, iValue):
		self._addYield(eYield, SPECIALISTS, iValue)
		
	def calculateCorporations(self, pCity):
		for eYield in range(YieldTypes.NUM_YIELD_TYPES):
			iValue = 0
			for eCorp in range(gc.getNumCorporationInfos()):
				if (pCity.isHasCorporation(eCorp)):
					iValue += pCity.getCorporationYieldByCorporation(eYield, eCorp)
			self.addCorporation(eYield, iValue)
	
	def addCorporation(self, eYield, iValue):
		self._addYield(eYield, CORPORATIONS, iValue)
	
	def calculateModifiers(self, pCity):
		for eYield in range(YieldTypes.NUM_YIELD_TYPES):
			iValue = pCity.getBaseYieldRateModifier(eYield, 0) - 100
			self._addYield(eYield, BASE_MODIFIER, iValue)
		
		# Depends on the item being built
		self.iProductionModifier = pCity.getProductionModifier()
		if self.iProductionModifier != 0:
			self.sModifierDetail = pCity.getProductionName()
	
	
	def fillTable(self, screen, table, eYield, eTileType):
		"""Fills the given GFC table control with the chosen yield values."""
		self.iRow = 0
		# Tiles
		iTotal = self.getYield(eYield, eTileType)
		self.appendTable(screen, table, False, BugUtil.getText(LABEL_KEYS[eTileType], (self.tileCounts[eTileType],)), eYield, iTotal)
		
		# Trade
		for eType in (DOMESTIC_TRADE, FOREIGN_TRADE):
			iValue = self.getYield(eYield, eType)
			if iValue != 0:
				self.appendTable(screen, table, False, BugUtil.getPlainText(LABEL_KEYS[eType]), eYield, iValue, TradeUtil.isFractionalTrade())
		iValue = self.getYield(eYield, DOMESTIC_TRADE) + self.getYield(eYield, FOREIGN_TRADE)
		if TradeUtil.isFractionalTrade():
			iValue //= 100
		iTotal += iValue
		
		# Buildings, Corporations, Specialists
		for eType in (BUILDINGS, CORPORATIONS, SPECIALISTS):
			iValue = self.getYield(eYield, eType)
			if iValue != 0:
				iTotal += iValue
				self.appendTable(screen, table, False, BugUtil.getPlainText(LABEL_KEYS[eType]), eYield, iValue)
		
		# Subtotal and Base Modifiers
		iModifier = self.getYield(eYield, BASE_MODIFIER)
		if iModifier != 0:
			# Subtotal
			self.appendTableTotal(screen, table, eYield, iTotal)
			#self.appendTable(screen, table, True, BugUtil.getPlainText("TXT_KEY_CONCEPT_SUBTOTAL"), eYield, iTotal)
			# Modifier
			iValue = (iTotal * (iModifier + 100) // 100) - iTotal
			iSubtotal = iTotal + iValue
			self.appendTable(screen, table, False, BugUtil.getText("TXT_KEY_CONCEPT_BASE_MODIFIER", (iModifier,)), eYield, iValue)
		else:
			iSubtotal = iTotal
		
		# Subtotal and Production Modifiers
		if eYield == YieldTypes.YIELD_PRODUCTION and self.iProductionModifier != 0:
			# Subtotal
			self.appendTableTotal(screen, table, eYield, iSubtotal)
			#self.appendTable(screen, table, True, BugUtil.getPlainText("TXT_KEY_CONCEPT_SUBTOTAL"), eYield, iSubtotal)
			# Total
			iTotal = iTotal * (iModifier + self.iProductionModifier + 100) // 100
			# Modifier
			iValue = iTotal - iSubtotal
			self.appendTable(screen, table, False, BugUtil.getText("TXT_KEY_CONCEPT_PRODUCTION_MODIFIER", (self.sModifierDetail, self.iProductionModifier)), eYield, iValue)
		else:
			iTotal = iSubtotal
		
		# Total
		self.appendTableTotal(screen, table, eYield, iTotal)
		#self.appendTable(screen, table, True, BugUtil.getPlainText("TXT_KEY_CONCEPT_TOTAL"), eYield, iTotal)
	
	def appendTable(self, screen, table, bTotal, heading, eYield, iValue, bFraction=False):
		"""
		Appends the given yield value to the table control.
		If bTotal is True, the heading is colored yellow and there's no + sign on the value.
		"""
		cYield = gc.getYieldInfo(eYield).getChar()
		screen.appendTableRow(table)
		if bTotal:
			heading = u"<color=205,180,55,255>%s</color>" % heading
			value = u"<color=205,180,55,255>%d</color>" % iValue
			if bFraction:
				# showing fraction doesn't fit in column
				value = u"<color=205,180,55,255>%d</color>" % (iValue // 100)
			else:
				value = u"<color=205,180,55,255>%d</color>" % iValue
		else:
			if bFraction:
				# showing fraction doesn't fit in column
				value = u"%+d" % (iValue // 100)
			else:
				value = u"%+d" % iValue
		screen.setTableText(table, HEADING_COLUMN, self.iRow, u"<font=1>%s</font>" % (heading), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_LEFT_JUSTIFY)
		screen.setTableText(table, VALUE_COLUMN, self.iRow, u"<font=1>%s%c</font>" % (value, cYield), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_RIGHT_JUSTIFY)
		self.iRow += 1

	def appendTableTotal(self, screen, table, eYield, iValue):
		"""
		Appends the given yield total to the table control's 3rd running total column.
		"""
		if self.iRow > 0:
			cYield = gc.getYieldInfo(eYield).getChar()
			value = u"<color=205,180,55,255>%d</color>" % iValue
			screen.setTableText(table, TOTAL_COLUMN, self.iRow - 1, u"<font=1>%s%c</font>" % (value, cYield), "", WidgetTypes.WIDGET_GENERAL, -1, -1, CvUtil.FONT_RIGHT_JUSTIFY)
