###############################################################################
#	Filename:	DryDock.py
#	
#	Confidential and Proprietary, Copyright 2001 by Totally Games
#	
#	Dry Dock region. Also contains Dry Dock control room character set.
#	
#	Created:	1/5/01 -	Alberto Fonseca
###############################################################################

import App
import Bridge.BridgeUtils
import MissionLib
import Bridge.Characters.Graff
import Bridge.HelmMenuHandlers
import Bridge.BridgeMenus
import BridgeHandlers
import Tactical.LensFlares
import loadspacehelper
import Foundation
import Bridge
import Bridge.EngineerMenuHandlers
import Actions.ShipScriptActions
import Lib.LibEngineering
import string
import math
import Bridge.BridgeUtils

ET_SBREPAIR = App.UtopiaModule_GetNextEventType()
ET_SBREARM = App.UtopiaModule_GetNextEventType()
ET_SBFINISH = App.UtopiaModule_GetNextEventType()

#NonSerializedObjects = ( "debug", )

#debug = App.CPyDebug(__name__).Print
#debug("Loading " + __name__ + " module...")

g_idDockAI 				= None
g_pMissionDatabase		= None
g_dRestoreScaleDict 		= {}

###############################################################################
#	Initialize()
#	
#	Initialize the Dry Dock set.
#	
#	Args:	pSet	- The Dry Dock set.
#	
#	Return:	none
###############################################################################
def Initialize(pSet):
	SetupEventHandlers(pSet)

	# Add a sun, far far away
	pSun = App.Sun_Create(1000.0, 1000, 500, "data/Textures/SunBlueWhite.tga", "data/Textures/Effects/SunFlaresWhite.tga")
	pSet.AddObjectToSet(pSun, "Sun")
	
	# Place the object at the specified location.
	pSun.PlaceObjectByName( "Sun" )
	pSun.UpdateNodeOnly()

	# Builds a Blue lens flare, attached to the sun
	Tactical.LensFlares.BlueLensFlare(pSet, pSun)

######
	# Create the Planet
	pPlanet = App.Planet_Create(180.0, "data/models/environment/BrownBluePlanet.nif")
	pSet.AddObjectToSet(pPlanet, "Tau Ceti Prime")
	
	# Place the object at the specified location.
	pPlanet.PlaceObjectByName( "Planet Location" )
	pPlanet.UpdateNodeOnly()

	# Get the sets we need
        if App.g_kUtopiaModule.IsHost() or not App.g_kUtopiaModule.IsMultiplayer():
	        pDryDockSet	= App.g_kSetManager.GetSet("DryDock")
	        global pDryDock, pDryDock2, pSUR
	        pDryDock	= loadspacehelper.CreateShip("DryDock", pSet, "DryDock", "DryDock Start")
	        pDryDock2	= loadspacehelper.CreateShip("DryDock", pSet, "DryDock 2", "DryDock2 Start")

	        pSUR	= loadspacehelper.CreateShip("Ambassador", pSet, "USS Samuel", "SUR")
	        pSUR.DisableGlowAlphaMaps()
	        pSUR.DestroySystem(pSUR.GetImpulseEngineSubsystem())
	        pSUR.DestroySystem(pSUR.GetTorpedoSystem())
	        pSUR.DestroySystem(pSUR.GetPhaserSystem())
	        pSUR.DestroySystem(pSUR.GetPulseWeaponSystem())
	        pSUR.DestroySystem(pSUR.GetShields())
	        pRepair = pSUR.GetRepairSubsystem()
	        pProp 	= pRepair.GetProperty()
	        pProp.SetMaxRepairPoints(0.0)


###############################################################################
#	SetupEventHandlers()
#	
#	Set up event handlers used by the Dry Dock set.
#	
#	Args:	pSet	- The Dry Dock set.
#	
#	Return:	none
###############################################################################
def SetupEventHandlers(pSet):
	pGame = App.Game_GetCurrentGame()
	pEpisode = pGame.GetCurrentEpisode()

	# Ship entrance event
	App.g_kEventManager.AddBroadcastPythonFuncHandler(App.ET_ENTERED_SET, pSet,
														__name__ + ".EnterSet")
	# Ship exit event
	App.g_kEventManager.AddBroadcastPythonFuncHandler(App.ET_EXITED_SET, pSet,
														__name__ + ".ExitSet")
	
###############################################################################
#	EnterSet(pObject, pEvent)
#	
#	Event handler for player's ship entering this set.
#	Create the Dry Dock Control Room Set when the player enters.
#	
#	Args:	
#	
#	Return:	
###############################################################################
def EnterSet(pObject, pEvent):
	pGame 	= App.Game_GetCurrentGame()
	pEpisode 	= pGame.GetCurrentEpisode()
	pMission 	= pEpisode.GetCurrentMission()
	pEnemies 	= pMission.GetEnemyGroup()
	pFriendlies = pMission.GetFriendlyGroup()

	try:
		# Get ship entering set.
		pShip = App.ShipClass_Cast(pEvent.GetDestination())

		# Get player.
		pPlayer = App.Game_GetCurrentPlayer()

		if pShip.GetObjID() != pPlayer.GetObjID():
			# This ship isn't the player's ship.  We're done.
			return
	except AttributeError:
		# Ship or Player is None.  Nothing to do here.
		return

	#Find what race it is
	ShipType = GetShipType(pPlayer.GetName())
	if not ShipType:
		return

        if App.g_kUtopiaModule.IsHost() or not App.g_kUtopiaModule.IsMultiplayer():

	        FdtnShip = Foundation.shipList[ShipType]
	        if not FdtnShip:
		        return

	        RaceName = FdtnShip.GetRace().name
	        if (RaceName == "Federation"):
        		if pShip.GetRadius() > 4.0:
			        # Ship's too big to fit through the doors.  Shrink it.
			        g_dRestoreScaleDict[pShip.GetObjID()] = pShip.GetScale()
			        pShip.SetScale( pShip.GetScale() / 4.0 / pShip.GetRadius() )
			        print("Good Federation Ships Can Dock")
			        pFriendlies.AddName(pSUR.GetName())
			        pFriendlies.AddName(pDryDock.GetName())			
			        pFriendlies.AddName(pDryDock2.GetName())
        
        	elif (RaceName == "Klingon"):
		        if pShip.GetRadius() > 4.0:
        			# Ship's too big to fit through the doors.  Shrink it.
			        g_dRestoreScaleDict[pShip.GetObjID()] = pShip.GetScale()
			        pShip.SetScale( pShip.GetScale() / 4.0 / pShip.GetRadius() )
			        print("Good Klingon Ships are Friends They can dock")
			        pFriendlies.AddName(pSUR.GetName())
			        pFriendlies.AddName(pDryDock.GetName())			
			        pFriendlies.AddName(pDryDock2.GetName())
        
        	else:
		        print("Im Sorry This Ship's Race Cannot Dock with A Federation DryDock")
		        pEnemies.AddName(pSUR.GetName())
		        pEnemies.AddName(pDryDock.GetName())			
		        pEnemies.AddName(pDryDock2.GetName())
		        return

	# The player is entering a set.  If they're entering the Dry Dock
	# set, setup the DD Control Room.
	if pShip.GetContainingSet().GetName() == "DryDock":
		SetupGraffSet()

###############################################################################
#	SetupGraffSet()
#	
#	Setup the Dry Dock Control Room set, so Graff can say something
#	if the player chooses to dock.  If the set already exists, this
#	does nothing.
#	
#	Args:	None
#	
#	Return:	None
###############################################################################
def SetupGraffSet():
	global pGraff
	pGraff = App.g_kSetManager.GetSet("FedOutpostSet_Graff")
	if not pGraff:
		pGraff = MissionLib.SetupBridgeSet("FedOutpostSet_Graff", "data/Models/Sets/FedOutpost/fedoutpost.nif", -30, 65, -1.55)
        try:
	        if not App.CharacterClass_GetObject(pGraff, "Graff"):
		        MissionLib.SetupCharacter("Bridge.Characters.Graff", "FedOutpostSet_Graff")
        except:
                pass


	# Enable Drydock button.
	import Lib.LibEngineering
	global pButton
	pButton = Lib.LibEngineering.CreateMenuButton("Dock With DryDock", "Helm", __name__ + ".DockDryDock")
	

	pGraff = None
	pGraff = GetGraff()
        if not pGraff:
                return
	pGraffMenu = Bridge.BridgeMenus.CreateBlankCharacterMenu(App.TGString("DryDock"), 0.3, 0.20, 0.65, 0.05)
	pGraff.SetMenu(pGraffMenu)
	pGraff.AddPythonFuncHandlerForInstance(ET_SBREPAIR, __name__ + ".Repair")	
	pGraff.AddPythonFuncHandlerForInstance(ET_SBREARM, __name__ + ".Rearm")
	pGraff.AddPythonFuncHandlerForInstance(ET_SBFINISH, __name__ + ".CloseChannel")
	pGraffMenu.AddChild(Bridge.BridgeUtils.CreateBridgeMenuButton(App.TGString("Begin Repairs"), ET_SBREPAIR, 0, pGraff)) 
	pGraffMenu.AddChild(Bridge.BridgeUtils.CreateBridgeMenuButton(App.TGString("Reload Torpedos"), ET_SBREARM, 0, pGraff))
	pGraffMenu.AddChild(Bridge.BridgeUtils.CreateBridgeMenuButton(App.TGString("Close Channel"), ET_SBFINISH, 0, pGraff))

def Repair(pObject, pEvent):
	# Get Player
	pPlayer 	= MissionLib.GetPlayer()
	pImpulse 	= pPlayer.GetImpulseEngineSubsystem()
	pTorpedo 	= pPlayer.GetTorpedoSystem()
	pPhasers 	= pPlayer.GetPhaserSystem()
	pPPhaser 	= pPlayer.GetPulseWeaponSystem()
	pShields 	= pPlayer.GetShields()
	pWarp		= pPlayer.GetWarpEngineSubsystem()
	pSensor 	= pPlayer.GetSensorSubsystem()
	pPower	= pPlayer.GetPowerSubsystem()
	pHull		= pPlayer.GetHull()

	if pHull:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pHull.GetObjID())
		Actions.ShipScriptActions.RepairShipFully(None, pPlayer.GetObjID())
	if pImpulse:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pImpulse.GetObjID())
	if pTorpedo:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pTorpedo.GetObjID())
	if pPhasers:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pPhasers.GetObjID())
	if pPPhaser:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pPPhaser.GetObjID())
	if pShields:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pShields.GetObjID())
	if pWarp:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pWarp.GetObjID())
	if pSensor:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pSensor.GetObjID())
	if pPower:
		Actions.ShipScriptActions.RepairSubsystemFully(None, pPower.GetObjID())
		pPlayer.GetPowerSubsystem().GetProperty().SetPowerOutput(pPlayer.GetPowerSubsystem().GetPowerOutput() / 6000)
		pPlayer.GetPowerSubsystem().GetProperty().SetPowerOutput(pPlayer.GetPowerSubsystem().GetPowerOutput() * 6000)
		pPower.SetMainBatteryPower(pPower.GetMainBatteryLimit())
		pPower.SetBackupBatteryPower(pPower.GetBackupBatteryLimit())

	print("Trying To Repair Ship")
	return 0

def Rearm(pObject, pEvent):
	# Get Player
	pPlayer = MissionLib.GetPlayer()
	if pPlayer is None:
		return 0
	print("Trying To Rearm Ship")

	# Charge ship's phasers.
	pPhaserSys = pPlayer.GetPhaserSystem()
	if(pPhaserSys):
		for iPhaserNum in range(pPhaserSys.GetNumChildSubsystems()):
			pPhaserBank = App.EnergyWeapon_Cast(pPhaserSys.GetChildSubsystem(iPhaserNum))
			pPhaserBank.SetChargeLevel(pPhaserBank.GetMaxCharge())

	# Charge ship's pulse weapons.
	pPulseSys = pPlayer.GetPulseWeaponSystem()
	if(pPulseSys):
		for iPulseNum in range(pPulseSys.GetNumChildSubsystems()):
			pPulseWeapon = App.EnergyWeapon_Cast(pPulseSys.GetChildSubsystem(iPulseNum))
			pPulseWeapon.SetChargeLevel(pPulseWeapon.GetMaxCharge())

	# Reload torpedo ammo and fill tubes.
	pTorpSys = pPlayer.GetTorpedoSystem()
	if(pTorpSys):
		# Load each ammo type.
		iNumTypes = pTorpSys.GetNumAmmoTypes()
		for iType in range(iNumTypes):
			pTorpSys.FillAmmoType(iType)
			# Fill torpedo tubes.
			pTorpSys.SetAmmoType(pTorpSys.GetAmmoTypeNumber(), 0)
	return 0

def CloseChannel(pObject, pEvent):
	pGraff.MenuDown()
	# Get Player
	pPlayer = MissionLib.GetPlayer()
	if pPlayer is None:
		return 0
	print("Trying To Close Channel")
	pSequence = App.TGSequence_Create()
	pSequence.AppendAction(App.TGScriptAction_Create("MissionLib", "ViewscreenOff"))
	pSequence.Play()
	return 0

def GetGraff():
	pDDSet = App.g_kSetManager.GetSet("FedOutpostSet_Graff")
	pGraff = App.CharacterClass_GetObject(pDDSet, "Graff")
	#assert pGraff
	return pGraff

###############################################################################
#	ExitSet(pObject, pEvent)
#	
#	Event handler for player's ship exiting this set.
#	Delete the Dry Dock Control Room Set when the player enters.
#
#	Args:	
#	
#	Return:	
###############################################################################
def ExitSet(pObject, pEvent):
	try:
		# Get ship exiting set.
		pShip = App.ShipClass_Cast(pEvent.GetDestination())

		# Get player.
		pPlayer = App.Game_GetCurrentPlayer()

		if pShip.GetObjID() != pPlayer.GetObjID():
			# This ship isn't the player's ship.  We're done.
			return
	except AttributeError:
		# Ship or Player is None.  Nothing to do here.
		return

	# The player's ship is exiting a set.  Check if it's exiting
	# the Dry Dock set...
	if pEvent.GetCString() == "DryDock":
		# Delete the Dry Dock Control Room Set.
		pDryDockControlSet = App.g_kSetManager.GetSet("FedOutpostSet_Graff")
		if pDryDockControlSet:
			App.g_kSetManager.DeleteSet("FedOutpostSet_Graff")
	
		Bridge.Characters.Graff.RemoveEventHandlers()

		# Disable dock button.
		if(pButton):
			pButton.SetNotVisible()

	# Restore the object size, if it was modified.
	if g_dRestoreScaleDict.has_key(pShip.GetObjID()):
		pShip.SetScale( g_dRestoreScaleDict[pShip.GetObjID()] )
		del g_dRestoreScaleDict[pShip.GetObjID()]

		
###############################################################################
#	DockDryDock():
#	
#	Make Player's ship dock/undock with Dry Dock.
#	
#	Args:	none
#	
#	Return:	none
###############################################################################
def DockDryDock(pShip, pObject):
	
# Take down Helm menu and turn character back.
	pBridgeSet = App.BridgeSet_Cast(App.g_kSetManager.GetSet("bridge"))
	pHelm = App.CharacterClass_GetObject (pBridgeSet, "Helm")
	if pHelm is None:
		return 0
	pHelm.MenuDown()
	pHelm.TurnBack()

	pPlayer = MissionLib.GetPlayer()
	# Set AI for docking/undocking.
	import AI.Compound.CakDockWithDryDock
        pDryDock2 = MissionLib.GetShip("DryDock 2")
	MissionLib.SetPlayerAI("Helm", AI.Compound.CakDockWithDryDock.CreateAI(pPlayer, pDryDock2))

def GetShipType(pShip):
	# thanks to mldaalder for the idea of using -1 instead of 1
	pPlayer = MissionLib.GetPlayer()
	pShip = App.ShipClass_Cast(pPlayer)
	return string.split(pShip.GetScript(), '.')[-1]
