################################################################
#
#   Bell Runner - Level Editor View
#
################################################################

from compat import reversed
from pygame import draw
from pygame.locals import *
from level_view import LevelView
from level import get_item_image, round_to_grid
from game import game

layer_sel_colors = [
	(0, 0, 255), # background
	(0, 255, 255), # gadgets
	(0, 255, 0), # platforms
	(255, 255, 0), # bells
	(255, 255, 0), # actors
	(255, 0, 0), # foreground
]

command_key_map = {
	K_f: 'bring_to_front_cmd',
	K_b: 'send_to_back_cmd',
}

key_map = {
	K_BACKSPACE: 'delete_cmd',
	K_DELETE: 'delete_cmd',
}

class LevelEditorView(LevelView):

	def draw(self, surf):
		LevelView.draw(self, surf)
		level = game.level
		selection = game.selection
		for color, layer in zip(layer_sel_colors, level.layers()):
			for item in layer:
				if item in selection:
					draw.rect(surf, color, item.rect, 1)
					for r in item.editor_handle_rects():
						draw.rect(surf, color, r, 1)

	def pick_item(self, p):
		level = game.level
		for layer in reversed(level.layers()):
			for item in reversed(layer):
				if item.rect.collidepoint(p):
					return item
	
	def pick_handle(self, p):
		for item in game.selection:
			for r in item.editor_handle_rects():
				if r.collidepoint(p):
					return item
	
	def mouse_down(self, e):
		tool = game.current_tool
		if tool == 'select':
			self.select_click(e)
		elif tool == 'add':
			self.add_click(e)
	
	def mouse_drag(self, e):
		tool = game.current_tool
		if tool == 'select':
			self.select_drag(e)
	
	def key_down(self, e):
		name = None
		if e.cmd:
			name = command_key_map.get(e.key)
		else:
			name = key_map.get(e.key)
		if name:
			getattr(self, name)()
		else:
			LevelView.key_down(self, e)
	
	def select_click(self, e):
		game.drag_pt = None
		game.drag_handle = None
		item = self.pick_handle(e.local)
		if item:
			game.drag_handle = item
			item.begin_handle_drag(e)
			return
		selection = game.selection
		item = self.pick_item(e.local)
		if item:
			if item in selection:
				if e.shift:
					selection.remove(item)
			else:
				if not e.shift:
					selection.clear()
				selection.add(item)
			if e.num_clicks == 2:
				if item.editable:
					if item.edit():
						game.level_changed()
			else:
				game.drag_pt = e.local
		else:
			if not e.shift:
				selection.clear()
	
	def select_drag(self, e):
		item = game.drag_handle
		if item:
			item.drag_handle(e)
			self.invalidate()
			return
		p = game.drag_pt
		if p:
			moved = False
			x1, y1 = game.drag_pt
			x2, y2 = e.local
			dx, dy = round_to_grid((x2 - x1, y2 - y1))
			if dx or dy:
				for item in game.selection:
					item.offset((dx, dy))
					moved = True
				game.drag_pt = x1 + dx, y1 + dy
			if moved:
				game.level_changed()
				self.invalidate()
	
	def add_click(self, e):
		kind = game.current_item_kind
		name = game.current_item_name
		if kind and name:
			rect = new_item_rect(e.local, kind, name)
			item = kind(rect, name)
			game.level.add_item(item)
			game.level_changed()

	def bring_to_front_cmd(self):
		level = game.level
		for item in game.selection:
			layer = level.find_layer(item)
			if layer:
				layer.remove(item)
				layer.append(item)
				game.level_needs_saving = True

	def send_to_back_cmd(self):
		level = game.level
		for item in game.selection:
			layer = level.find_layer(item)
			if layer:
				layer.remove(item)
				layer.insert(0, item)
				game.level_needs_saving = True

	def delete_cmd(self):
		level = game.level
		done = False
		for item in game.selection:
			if item.deletable:
				layer = level.find_layer(item)
				if layer:
					layer.remove(item)
					done = True
		if done:
			game.level_changed()


def new_item_rect(p, kind, name):
	image = get_item_image(kind, name)
	r = image.get_rect()
	r.center = p
	r.topleft = round_to_grid(r.topleft)
	return r

