################################################################
#
#   Bell Runner - Player
#
################################################################

from pygame import transform
from albow.image_array import ImageArray
from albow.resource import get_image
from vector_algebra import add2, sub2
from level import Item

#--------------------------------------------------------------------------

#  Player facing directions

FACE_LEFT = -1
FACE_FRONT = 0
FACE_RIGHT = 1

#  Player actions

ACT_STAND = 0
ACT_WALK = 1
ACT_HANG = 2

#  Animation parameters

num_walking_frames = 12
walk_advance = 8
falling_speed = 16
grabbing_height = 92 # from feet to hands holding rope

def load_walking_frames():
	left_image = get_image("player/walking.png", border = 2)
	left_array = ImageArray(left_image, num_walking_frames)
	right_image = transform.flip(left_image, True, False)
	right_array = ImageArray(right_image, num_walking_frames)
	return [left_array, right_array]

#--------------------------------------------------------------------------

class Player(Item):
	#  position             point   Position of contact point with ground
	#  initial_position     point
	#  supported            boolean
	
	deletable = False
	standing_frame = get_image("player/standing.png", border = 2)
	falling_frame = get_image("player/falling.png", border = 2)
	hanging_frame = get_image("player/hanging.png", border = 2)
	walking_frames = load_walking_frames()
	step_height = 16
	
	supported = True
	nearby_rope = None
	holding_rope = None
	unsupported_time = 0
	platform_was_behind = False

	def __init__(self, pos):
		self.initial_position = pos
		self.reset()
	
	def reset(self):
		self.position = self.initial_position
		self.supported = True
		self.nearby_rope = None
		self.holding_rope = None
		self.facing = FACE_FRONT
		self.action = ACT_STAND
		self.frame = 0
	
	def get_rect(self):
		image = self.standing_frame
		r = image.get_rect()
		r.midbottom = self.position
		return r
	
	def get_grab_position(self):
		x, y = self.position
		return (x, y - grabbing_height)
		#return sub2(self.position, (0, grabbing_height))
	
	def set_grab_position(self, p):
		x, y = p
		self.position = (x, y + grabbing_height)
	
	def offset(self, delta):
		p = add2(self.initial_position, delta)
		self.initial_position = p
		self.position = p
	
	rect = property(get_rect)

	def draw(self, surf):
		face = self.facing
		act = self.action
		if act == ACT_HANG:
			image = self.hanging_frame
		elif self.unsupported_time >= 2:
			image = self.falling_frame
		elif act == ACT_WALK:
			i = 0
			j = self.frame
			if face == FACE_RIGHT:
				i = 1
				j = num_walking_frames - j - 1
			image = self.walking_frames[i][j]
		else:
			image = self.standing_frame
		r = image.get_rect()
		r.midbottom = self.position
		surf.blit(image, r)
	
	def begin_frame(self, level):
		x, y = self.position
		dx = dy = 0
		if self.supported:
			self.unsupported_time = 0
			dy = self.support_height - self.position[1]
			act = self.action
			if act == ACT_WALK:
				f = self.frame + 1
				if f >= num_walking_frames:
					f = 0
				self.frame = f
				dx = self.facing * walk_advance
		else:
			dy = falling_speed
			self.unsupported_time += 1
		x2 = x + dx
		y2 = y + dy
		if not level.actor_can_walk_to(self, (x2, y2)):
			x2 = x
		self.position = (x2, y2)

	def start_walking(self, face):
		if self.action == ACT_STAND:
			self.action = ACT_WALK
			self.frame = 0
		self.facing = face
	
	def stop_walking(self, face):
		if self.action == ACT_WALK and self.facing == face:
			self.stand_still()
	
	def stand_still(self):
		self.action = ACT_STAND
		self.facing = FACE_FRONT
		self.frame = 0
	
	def grab_or_release_rope(self):
		if self.holding_rope:
			self.release_rope()
		else:
			self.grab_rope()

	def grab_rope(self):
		bell = self.nearby_rope
		if bell:
			self.holding_rope = bell
			bell.rope_held_by(self, self.get_grab_position())
			x, y = self.position
			r = bell.get_rope_rect()
			self.position = (r.centerx, y)
			self.action = ACT_HANG
			self.frame = 0

	def release_rope(self):
		bell = self.holding_rope
		if bell:
			self.holding_rope = None
			bell.rope_held_by(None, None)
			self.stand_still()
