"""
HeavyFlag, a OneCTF adaptation
by Shrub, originally by Yourself

References: onectf.py, koth.py
"""

from pyspades.constants import *
from commands import add, admin
from twisted.internet.task import LoopingCall
from twisted.internet.reactor import seconds,callLater

FLAG_SPAWN_POS = (256, 256)
HIDE_POS = (0, 0, 63)
HEAVY_FLAG_MESSAGE = "You can't use weapons while you're carrying the Intel!"

# Time needed to capture the case, in seconds
HOLD_TIME = 120

def apply_script(protocol, connection, config):

	class HeavyFlagProtocol(protocol):
		game_mode = CTF_MODE

		def onectf_reset_flag(self, flag):
			"""resets the flag upon game end, from onectf"""
			z = self.map.get_z(*self.one_ctf_spawn_pos)
			pos = (self.one_ctf_spawn_pos[0], self.one_ctf_spawn_pos[1], z)
			if flag is not None:
				flag.player = None
				flag.set(*pos)
				flag.update()
			return pos

		def on_game_end(self):
			"""Resets flags at the end of the game, from onectf"""
			self.onectf_reset_flag(self.blue_team.flag)
			self.onectf_reset_flag(self.green_team.flag)
			# My hookcraft is full of swallowing
			return protocol.on_game_end(self)

		def on_map_change(self, map):
			"""Set flag spawn and load map extensions"""
			self.one_ctf_spawn_pos = FLAG_SPAWN_POS
			extensions = self.map_info.extensions
			if extensions.has_key('one_ctf_spawn_pos'):
				self.one_ctf_spawn_pos = extensions['one_ctf_spawn_pos']
			# Only the Sith deal in hook swallowing
			return protocol.on_map_change(self, map)

		def on_flag_spawn(self, x, y, z, flag, entity_id):
			"""
			Moves the flag to the
			spawn pos on spawn,
			from onectf
			"""
			pos = self.onectf_reset_flag(flag.team.other.flag)
			protocol.on_flag_spawn(self, pos[0], pos[1], pos[2], flag, entity_id)
			return pos

		def start_count(self):
			"""Sets a time to call self.win later"""
			self.end = HOLD_TIME + seconds()
			callLater(HOLD_TIME, self.win)

		def win(self):
			"""Checks the win condition, from koth"""
			if self.green_team.flag.player:
				player = self.green_team.flag.player
			elif self.blue_team.flag.player:
				player = self.blue_team.flag.player
			else:
				player = None
			if player:
				if self.end and self.end - seconds() < 5:
					#self.send_chat("Winner!")
					self.reset_game(player)
					protocol.on_game_end(self)

	class HeavyFlagConnection(connection):
		def on_flag_take(self):
			"""
			Takes care of the things
			that happen on the taking
			of the flag
			"""
			# Hide own team's flag
			flag = self.team.flag
			if flag.player is None:
				flag.set(*HIDE_POS)
				flag.update()
			else:
				return False
			# Disable weapon by removing all ammo
			self.flag = True
			self.weapon_object.current_ammo = 0
			self.weapon_object.current_stock = 0
			self.grenades = 0
			self.blocks = 0
			# Reloads to remove weapon
			self._on_reload()
			# Display message to capper
			self.send_chat(HEAVY_FLAG_MESSAGE)
			self.protocol.send_chat("Only %d seconds until the Intel is captured!" % (HOLD_TIME))
			# Start countdown
			self.protocol.start_count()
			# One does not simply swallow the hook
			return connection.on_flag_take(self)

		def on_flag_drop(self):
			"""Resets the flag, from one_ctf"""
			flag = self.team.flag
			position = self.world_object.position
			x, y, z = int(position.x), int(position.y), max(0, int(position.z))
			z = self.protocol.map.get_z(x, y, z)
			flag.set(x, y, z)
			flag.update()
			self.flag = False
			# To swallow or not to swallow, that is the question
			return connection.on_flag_drop(self)

		def capture_flag(self):
			"""Prevents flag from being captured"""
			return False

		def on_grenade_thrown(self, grenade):
			"""Prevents grenade throw if player has flag"""
			if self.flag is not None or False:
				connection.on_grenade_thrown(self, grenade)
				return False
			else:
				return on_grenade_thrown(self, grenade)

		def on_block_build_attempt(self, x, y, z):
			"""Prevents blocks being built if player has flag"""
			if self.flag is not None or False:
				connection.on_block_build_attempt(self, x, y, z)
				return False
			else:
				return on_block_build_attempt(self, x, y, z)

		def on_line_build_attempt(self, x, y, z):
			"""Prevents blocks being built if player has flag"""
			if self.flag is not None or False:
				connection.on_line_build_attempt(self, x, y, z)
				return False
			else:
				return on_line_build_attempt(self, x, y, z)


	# Return the Protocol and Connection
	return HeavyFlagProtocol, HeavyFlagConnection