## Unit Plot List Utilities
##
## Holds the information used to display the unit plot list
##
## Copyright (c) 2007-2009 The BUG Mod.
##
## Author: Ruff_Hi

from CvPythonExtensions import *
import MonkeyTools as mt
import BugUtil

# globals
gc = CyGlobalContext()
ArtFileMgr = CyArtFileMgr()
localText = CyTranslator()

iLeaderPromo = gc.getInfoTypeForString('PROMOTION_GREAT_COMMANDER')
sFileNamePromo = ArtFileMgr.getInterfaceArtInfo("OVERLAY_PROMOTION_FRAME").getPath()
#screen = CyGInterfaceScreen( "MainInterface", CvScreenEnums.MAIN_INTERFACE )

# constants
(sUpdateShow,
 sUpdateShowIf,
 sUpdateHide,
 sUpdateNothing,
) = range(4)


sBupStringBase = "BUGUnitPlotString"
cUplSize = 34
cUplSpacing = 3

def updatePLEOptions():
	# Capture these for looping over the plot's units
	self.bShowWoundedIndicator = PleOpt.isShowWoundedIndicator()
	self.bShowGreatGeneralIndicator = PleOpt.isShowGreatGeneralIndicator()
	self.bShowPromotionIndicator = PleOpt.isShowPromotionIndicator()
	self.bShowUpgradeIndicator = PleOpt.isShowUpgradeIndicator()
	self.bShowMissionInfo = PleOpt.isShowMissionInfo()
	self.bShowHealthBar = PleOpt.isShowHealthBar()
	self.bHideHealthBarWhileFighting = PleOpt.isHideHealthFighting()
	self.bShowMoveBar = PleOpt.isShowMoveBar()

## Notes:
## - the vanilla BtS unit plot list has a panel for each row of icons and the units are arranged from the bottom left
## - the PLE unit plot list has no panel (drawn straight onto the screen) and counts from the top left (when in standard format)
## - the BUG unit plot list has one big panel and counts from the bottom left
##    - this means that the max'th row fills up first, then the max'th-1, etc.
## - x counts the columns across the panel, from 0 to max - 1
## - y counts the rows down the panel, from 0 to max - 1

## _getx and _gety return the number of pixels for each unitplot from the top left of the panel (not from the top left of the screen!)

class UnitList:
	def __init__(self, vScreen, vCols, vRows, yRes):
		self.screen = vScreen
		self.iCols = vCols
		self.iRows = vRows
		self.sBupPanel = sBupStringBase + "BackgroundPanel"

		_x = 315 - cUplSpacing
		_y = yRes - 169 - cUplSpacing + (1 - vRows) * cUplSize
		_w = vCols * cUplSize + cUplSpacing
		_h = vRows * cUplSize + cUplSpacing
		screen.addPanel(sBupPanel, u"", u"", True, False, _x, _y, _w, _h, PanelStyles.PANEL_STYLE_EMPTY)

		UnitPlots = []
		for i in range(vCols * vRows):
			UnitPlots.append(UnitPlot(sBupPanel, i, _getx(i), _gety(i)))

	def _getx(self, iIndex):
		_col = iIndex % iCols
		return _col - 1

	def _gety(self, iIndex):
		_row = iIndex / iCols
		return iRows - irow

	def _getIndex(self, x, y):
		return (iRows - y) * iCols + x - 1


#	def getMaxCol(self):
#		return ((self.xResolution - (iMultiListXL+iMultiListXR) - 68) / 34)
#		
#	def getMaxRow(self):
#		return ((self.yResolution - 160) / PleOpt.getVerticalSpacing()) 
#		
#	def getRow(self, i):
#		return i / self.getMaxCol()

#	def getCol(self, i):
#		return i % self.getMaxCol()
#		
#	def getX(self, nCol):
#		return 315 + (nCol * PleOpt.getHoriztonalSpacing())
#		
#	def getY(self, nRow):
#		return self.yResolution - 169 - (nRow * PleOpt.getVerticalSpacing())
#		
#	def getI(self, nRow, nCol):
#		return ( nRow * self.getMaxCol() ) + ( nCol % self.getMaxCol() )






## - xPixel is the number of horizontal pixels from the top left of the BUG unit plot list panel
## - yPixel is the number of vertically pixels from the top left of the BUG unit plot list panel



class UnitPlot:
	def __init__(self, vBupPanel, iIndex, x, y):
		self.sBupString = sBupStringBase + str(iIndex)
		xPixel = _getxPixel(x)
		yPixel = _getyPixel(x)

		# add promo frame
		screen.addDDSGFCAt(_getPromoString(), vBupPanel, sFileNamePromo, xPixel + 2, yPixel + 2, 32, 32, WidgetTypes.WIDGET_PLOT_LIST, iIndex, -1, False )
		screen.hide(_getPromoString())


	def _getxPixel(self, x):
		return x * cUplSize + cUplSpacing

	def _getyPixel(self, y):
		return y * cUplSize + cUplSpacing

#		_updatePromo(_getPromoString(), None, None, sUpdateNew)
#cUplSize = 34
#cUplSpacing = 3



#				szStringPromoFrame  = szString + "PromoFrame"









#		for i in range( self.iMaxPlotListIcons ):
#			szString = self.PLOT_LIST_BUTTON_NAME + str(i)
#			screen.hide( szString )
#			screen.hide( szString + "Icon" )
#			screen.hide( szString + "HealthBar" )
#			screen.hide( szString + "MoveBar" )
#			screen.hide( szString + "PromoFrame" )
#			screen.hide( szString + "ActionIcon" )
#			screen.hide( szString + "Upgrade" )



	def reset(self):
		pCurrUnit = None

	def refresh(self, pUnit):  # or should this be draw()?
		self.pPrevUnit = pCurrUnit
		self.pCurrUnit = UnitDisplay(pUnit)

		# Unit Plot
		if self.pCurrUnit == None:
			if self.pPrevUnit != None:
				# current unit is blank, previous unit was not blank
				_erasePromo()
			#else:
				# current unit is blank, previous unit was blank
				# nothing to do
		else:
			if self.pPrevUnit != None:
				# current unit is not blank, previous unit was not blank
				_updatePromo()
			else:
				# current unit is not blank, previous unit was blank
				_drawPromo()










	def _updatePromo():
		if not self.pPrevUnit.bPromo:
			self._showPromo()
		elif not self.pCurrUnit.bPromo:
			self._hidePromo()

	def _drawPromo():
		# test if you really want to show it
		if self.pPrevUnit == None:
			if self.pCurrUnit.bPromo:
				_showPromo()
		else:
			if (self.pCurrUnit.bPromo
			and not self.pPrevUnit.bPromo):
				_showPromo()

	def _erasePromo():
		# test if you really want to hide it
		if self.pCurrUnit == None:
			if self.pPrevUnit.bPromo:
				_hidePromo()
		else:
			if (self.pPrevUnit.bPromo
			and not self.pCurrUnit.bPromo):
				_hidePromo()

	def _hidePromo():
		# just hide the stupid thing
		self.screen.hide(_getPromoString())

	def _showPromo():
		# just show the stupid thing
		self.screen.show(_getPromoString())





	def _getPromoString():
		return self.sBupString + "PromoFrame"





class UnitDisplay:
	def __init__(self, pUnit):
		self.bSelected = pUnit.IsSelected()
		self.eUnit = pUnit.getUnitType()
		self.sDotState, self.iDotxSize, self.iDotySize, self.iDotxOffset, self.iDotyOffset = _getDOTInfo(pUnit)
		self.sMission = _getMission(pUnit)
		self.bPromo = pUnit.isPromotionReady()
		self.bGG = iLeaderPromo != -1 and pUnit.isHasPromotion(iLeaderPromo)
		self.bUpgrade = mt.checkAnyUpgrade(pUnit)
		self.icurrHitPoints = pUnit.currHitPoints()
		self.imaxHitPoints = pUnit.maxHitPoints()
		self.iMovesLeft = pUnit.movesLeft()
		self.iMoves = pUnit.getMoves()

	def _getDOTInfo(self, pUnit):
		xSize = 12
		ySize = 12
		xOffset = 0
		yOffset = 0

		if ((pUnit.getTeam() != gc.getGame().getActiveTeam()) or pUnit.isWaiting()):
			# fortified
			szDotState = "OVERLAY_FORTIFY"
		elif (pUnit.canMove()):
			if (pUnit.hasMoved()):
				# unit moved, but some movement points are left
				szDotState = "OVERLAY_HASMOVED"
			else:
				# unit did not move yet
				szDotState = "OVERLAY_MOVE"
		else:
			# unit has no movement points left
			szDotState = "OVERLAY_NOMOVE"

		# Wounded units will get a darker colored button.
		if (self.bShowWoundedIndicator) and (pUnit.isHurt()):
			szDotState += "_INJURED"

		# Units lead by a GG will get a star instead of a dot.
		if (self.bShowGreatGeneralIndicator):
			# is unit lead by a GG?
			if (iLeaderPromo != -1 and pUnit.isHasPromotion(iLeaderPromo)):
				szDotState += "_GG"
				xSize = 16
				ySize = 16
				xOffset = -3
				yOffset = -3

		return szDotState, xSize, ySize, xOffset, yOffset

	def _getMission(self, pUnit):
		eActivityType = pUnit.getGroup().getActivityType()
		eAutomationType = pUnit.getGroup().getAutomateType()

		# is unit on air intercept mission
		if (eActivityType == ActivityTypes.ACTIVITY_INTERCEPT):
			return "OVERLAY_ACTION_INTERCEPT"
		# is unit on boat patrol coast mission
		elif (eActivityType == ActivityTypes.ACTIVITY_PATROL):
			return "OVERLAY_ACTION_PATROL"
		# is unit on boat blockade mission
		elif (eActivityType == ActivityTypes.ACTIVITY_PLUNDER):
			return "OVERLAY_ACTION_PLUNDER"
		# is unit fortified for healing (wake up when healed)
		elif (eActivityType == ActivityTypes.ACTIVITY_HEAL):
			return "OVERLAY_ACTION_HEAL"
		# is unit sentry (wake up when enemy in sight)
		elif (eActivityType == ActivityTypes.ACTIVITY_SENTRY):
			return "OVERLAY_ACTION_SENTRY"
		# is the turn for this unit skipped (wake up next turn)
		elif (eActivityType == ActivityTypes.ACTIVITY_HOLD):
			return "OVERLAY_ACTION_SKIP"
		# has unit exploration mission
		elif (eAutomationType == AutomateTypes.AUTOMATE_EXPLORE):
			return "OVERLAY_ACTION_EXPLORE"
		# is unit automated generally (only worker units)
		elif (eAutomationType == AutomateTypes.AUTOMATE_BUILD):
			return "OVERLAY_ACTION_AUTO_BUILD"
		# is unit automated for nearest city (only worker units)
		elif (eAutomationType == AutomateTypes.AUTOMATE_CITY):
			return "OVERLAY_ACTION_AUTO_CITY"
		# is unit automated for network (only worker units)
		elif (eAutomationType == AutomateTypes.AUTOMATE_NETWORK):
			return "OVERLAY_ACTION_AUTO_NETWORK"
		# is unit automated spread religion (only missionary units)
		elif (eAutomationType == AutomateTypes.AUTOMATE_RELIGION):
			return "OVERLAY_ACTION_AUTO_RELIGION"
		# has unit a mission
		elif (pUnit.getGroup().getLengthMissionQueue() > 0):
			eMissionType = pUnit.getGroup().getMissionType(0)
			# is the mission to build an improvement
			if (eMissionType == MissionTypes.MISSION_BUILD):
				return "OVERLAY_ACTION_BUILD"
			# is the mission a "move to" mission
			elif (eMissionType in UnitUtil.MOVE_TO_MISSIONS):
				return "OVERLAY_ACTION_GOTO"
		# if nothing of above, but unit is waiting -> unit is fortified
		elif (pUnit.isWaiting()):
			if (pUnit.isFortifyable()):
				return "OVERLAY_ACTION_FORTIFY"
			else:
				return "OVERLAY_ACTION_SLEEP"

		return ""
