"""
Bury the Base v0.7
by Shrub

References: babel_script.py, babel.py, tow.py,
onectf.py
"""

# Imports constants pyspades to make lines shorter, but harder to understand?
from pyspades.constants import *
from pyspades.types import MultikeyDict

# Define static variables
BLUE_BASE = (32, 32)
GREEN_BASE = (64, 64)
BLUE_TOWER_COLOUR = (0, 0, 255)
GREEN_TOWER_COLOUR = (0, 255, 0)
TOWER_RADIUS = 4
TOWER_HEIGHT = 30

# Unused as of now
SPAWN_RADIUS = (0, 0)

# TOW had this so I figured I should add it
HELP = [
	"In Bury the Base, you dig under the enemy base until it hits the ground"
]

# Dat apply_script method
def apply_script(protocol, connection, config):
	"""Allows script to be run"""

	class BtbProtocol(protocol):
		"""Hooks into the protocol class to run protocol functions"""
		# Specify CTF game-mode as a base to work on
		game_mode = CTF_MODE

		def on_map_change(self, map):
			"""Initializses the map"""
			# Set the variables up
			self.blue_base = BLUE_BASE
			self.green_base = GREEN_BASE

			# Assign first values to both bases, if not already
			if self.blue_base == None:
				self.blue_base = self.get_random_location(False, (16, 16, 192, 496))
				# Finds a new base position until the base is above the ground
				while self.blue_base[2] >= 62:
					self.blue_base = self.get_random_location(False, (16, 16, 192, 496))
			else:
				self.blue_base = (BLUE_BASE[0], BLUE_BASE[1], 62 - TOWER_HEIGHT)
			if self.green_base == None:
				self.green_base = self.get_random_location(False, (320, 16, 496, 496))
				while self.green_base[2] >= 62:
					self.green_base = self.get_random_location(False, (320, 16, 496, 496))
			else:
				self.green_base = (GREEN_BASE[0], GREEN_BASE[1], 62 - TOWER_HEIGHT)

			# Run the tower building module
			self.build_tower(self.blue_base, map, BLUE_TOWER_COLOUR)
			self.build_tower(self.green_base, map, GREEN_TOWER_COLOUR)

			# Prevent the asphyxiation of the hook
			return protocol.on_map_change(self, map)


		def build_tower(self, base, map, colour):
			# Assign some neat variables, lower is the variable where the range starts
			upper_z = 62 - TOWER_HEIGHT

			# Tower X and Y limits are TOWER_RADIUS away from base
			lower_x = base[0] - TOWER_RADIUS
			upper_x = base[0] + TOWER_RADIUS
			lower_y = base[1] - TOWER_RADIUS
			upper_y = base[1] + TOWER_RADIUS

			# Count along the z-axis, x-axis and y-axis, respectively, placing blocks
			for z in range(upper_z, 62):
				for x in range(lower_x, upper_x):
					for y in range(lower_y, upper_y):
						map.set_point(x, y, z, colour)

		def on_base_spawn(self, x, y, z, base, entity_id):
			"""Assigns bases to their predefined positions"""

			# Checks which side of the map the base is on to discern the base
			if x < 256:
				pos = self.blue_base
			else:
				pos = self.green_base
			# The hook is not for dinner
			protocol.on_base_spawn(self, pos[0], pos[1], (62 - TOWER_HEIGHT), base, entity_id)
			return pos

		def on_update_entity(self, entity):
			"""
			Checks if either base hits the lowest
			block whenever an entity updates
			"""
			if self.green_team.base.z >= 62:
				protocol.reset_game(self, self.getBlue())
				# I'll leave these until I fix that reset bug
				#self.build_tower(self.blue_base, self.map, BLUE_TOWER_COLOUR)
				#self.build_tower(self.green_base, self.map, GREEN_TOWER_COLOUR)
			if self.blue_team.base.z >= 62:
				protocol.reset_game(self, self.getGreen())
				#self.build_tower(self.blue_base, self.map, BLUE_TOWER_COLOUR)
				#self.build_tower(self.green_base, self.map, GREEN_TOWER_COLOUR)

			# Dun swallah da hewk!
			return protocol.on_update_entity(self, entity)

		def getBlue(self):
			"""Creates a fake Blue player to spoof the team because lazy"""
			player = MultikeyDict()
			player.name = "Deuce"
			player.player_id = 99
			player.tool = 0
			player.weapon = 0
			player.kills = 0
			player.team = self.blue_team
			player.color = (0, 0, 0)
			return player

		def getGreen(self):
			"""Creates a fake Green player to spoof the team because lazy"""
			player = MultikeyDict()
			player.name = "Deuce"
			player.player_id = 99
			player.tool = 0
			player.weapon = 0
			player.kills = 0
			player.team = self.green_team
			player.color = (0, 0, 0)
			return player

		def on_flag_spawn(self, x, y, z, flag, entity_id):
			"""Sends the flags to the corner of the map"""
			# I nicked this snipped from onectf.py
			pos = (0, 0, 63)
			# Hooks are inedible
			protocol.on_flag_spawn(self, pos[0], pos[1], pos[2], flag, entity_id)
			return pos


	class BtbConnection(connection):
		"""Hooks into the connection class"""
		def on_flag_take(self):
			"""Prevents the flag from being taken"""
			return False
			# Do I even need this line
			return connection.on_flag_take(self)

	# Returns the protocol and connection to server.py
	return BtbProtocol, BtbConnection

# Volans minimum, volans caecum

# -------------------------------------------------------------------------------------
# To-do
# - Fix game win attribution
# - Fix game reset tower creation
# - Add radial spawning
# - Fix " has captured the Green Intel"
# -------------------------------------------------------------------------------------