/keygraph.py
import pygame
from bmevent import *
from keyhandler import *
from keyfile import BMEListIter
from fx import ColumnPulse
from constants import *

red = (255,30,30)
offwhite = (245,245,245)
blue = (30,30,255)
black = (0,0,0)
darkgray = (20,20,20)

class KeyGraph:
	keyfile = None
	t = 0
	b = 0
	velocity = 150.0
	li = None
	bordercolor = (255,255,255)
	judgemapping = {JUDGE_FGREAT: ["gfx/great.png","gfx/fgreat.png"],
			JUDGE_GREAT: ["gfx/great.png"],
			JUDGE_GOOD: ["gfx/good.png"],
			JUDGE_BAD: ["gfx/bad.png"],
			JUDGE_POOR: ["gfx/poor.png"],
			JUDGE_NA: []}
	colmarkmap = {JUDGE_FGREAT: "gfx/dcircle.png",
		      JUDGE_GREAT: "gfx/circle.png",
		      JUDGE_GOOD: "gfx/triangle.png",
		      JUDGE_BAD: "gfx/cross.png",
		      JUDGE_POOR: "gfx/cross.png",
		      JUDGE_NA: None}
	numberfiles = ["gfx/glyph/0.png","gfx/glyph/1.png","gfx/glyph/2.png","gfx/glyph/3.png","gfx/glyph/4.png","gfx/glyph/5.png","gfx/glyph/6.png","gfx/glyph/7.png","gfx/glyph/8.png","gfx/glyph/9.png"]
	
	def __init__(self, kf, keystyle, player, disprect):
		self.numkeys = len(keystyle)
		self.keyfile = kf
		self.screen = pygame.display.get_surface()
		self.disprect = disprect
		self.vheight = disprect.height - 5;
		self.barrect = pygame.Rect(disprect.left,
					   disprect.bottom - 4,
					   disprect.width,
					   5)
		if player == 1:
			self.notefilter = BME_NOTE1
		elif player == 2:
			self.notefilter = BME_NOTE2
		else:
			print "Invalid player given to keygraph: " + kf
			exit(1)
		self.t = 0
		self.b = 0
		self.li = BMEListIter(self.keyfile.bmelist)
		self.keystyle = []

		w = 0
		tw = sum(map(lambda x: x[0],keystyle))
		for x in keystyle:
			self.keystyle.append((int(w),x[1],x[2]))
			w += (x[0] / tw) * (disprect.width - 1)
		self.keystyle.append((int(w),None,None))

		# Load gfx
		self.judgeimg = {}
		for k in self.judgemapping.keys():
			self.judgeimg[k] = map(lambda y: pygame.image.load(y).convert_alpha(),self.judgemapping[k])
		self.colmarkimg = {}
		for k in self.colmarkmap.keys():
			if self.colmarkmap[k]:
				self.colmarkimg[k] = pygame.image.load(self.colmarkmap[k]).convert_alpha()
			else:
				self.colmarkimg[k] = None
		self.colmarkimg[0] = None
		self.numberimg = map(lambda y: pygame.image.load(y).convert_alpha(),self.numberfiles)
		self.judgement = 0
		self.kjudgement = [0 for x in range(0,self.numkeys)]
		self.judgetime = 0
		self.kjudgetime = [0 for x in range(0,self.numkeys)]
		self.combo = 0

		# Initialize keypulses (they are neat)
		self.pulse = []
		for n in range(0,len(keystyle)):
			x = self.keystyle[n][0] + 1
			y = self.disprect.top + 0.3 * self.disprect.height
			w = self.keystyle[n+1][0] - self.keystyle[n][0] - 1
			h = 0.7 * self.disprect.height - 4
			self.pulse.append(ColumnPulse(pygame.Rect(x,y,w,h),keystyle[n][3]))
		self.accuracy = 0
		self.key = 0

	def setproperties(self,properties):
		try:
			ud = properties['ud']
			k = properties['key']
			if ud == 1:
				self.pulse[k].down()
			else:
				self.pulse[k].up()
			self.key = k
		except KeyError:
			pass

		try:
			self.judgement = properties['judgement']
			self.kjudgement[self.key] = properties['judgement']
			self.judgetime = self.t
			self.kjudgetime[self.key] = self.t
			if self.judgement <= JUDGE_GOOD:
				self.combo += 1
			else:
				self.combo = 0
		except KeyError:
			pass

		try:
			self.accuracy = properties['accuracy']
		except KeyError:
			pass

	def numimgs(self,n):
		imgs = []
		while n:
			imgs.append(self.numberimg[n % 10])
			n = n / 10
		imgs.reverse()
		return imgs

	def draw(self):
		self.b = self.keyfile.eval_beatfunc(self.t)
		for n in range(0,self.numkeys):
			x = self.disprect.left + self.keystyle[n][0]
			w = self.keystyle[n+1][0] - self.keystyle[n][0]
			self.screen.fill(self.keystyle[n][2],
				(x,self.disprect.top,w,self.disprect.height))
		for n in range(0,self.numkeys+1):
			pygame.draw.line(self.screen, self.bordercolor,
				(self.disprect.left + self.keystyle[n][0], self.disprect.top),
				(self.disprect.left + self.keystyle[n][0], self.disprect.bottom - 1) )

		self.li.goto(self.b)
		keylist = self.li.window(self.vheight / self.velocity, self.notefilter)
		pygame.draw.rect(self.screen, (255,0,0), self.barrect)
		distortion = 1.0
		for k in keylist:
			y = self.disprect.top + self.vheight - int((k.beat - self.b) * (self.velocity / distortion))
			x = self.disprect.left + self.keystyle[k.key][0] + 1
			w = self.keystyle[k.key+1][0] - self.keystyle[k.key][0] - 1
			pygame.draw.rect(self.screen, self.keystyle[k.key][1], (x,y,w,5) )
		for n in self.pulse:
			n.draw()

		if self.judgement:
			if self.t - self.judgetime > 500:
				self.judgement = 0
			elif len(self.judgeimg[self.judgement]) == 0:
				pass
			else:
				z = (self.t / 60) % len(self.judgeimg[self.judgement])
				w = self.judgeimg[self.judgement][z].get_width()
				x = self.disprect.left + (self.disprect.width / 2) - (w / 2)
				y = self.disprect.top + self.disprect.height * 0.7
				if self.combo >= 2:
					imgs = self.numimgs(self.combo)
					x -= 2
					w += 4
					for i in imgs:
						x -= i.get_width() / 2
					for i in imgs:
						self.screen.blit(i,(x + w,y))
						w += i.get_width()
				self.screen.blit(self.judgeimg[self.judgement][z],(x,y))
				# Draw accuracy bar
				x = self.disprect.left + self.disprect.width / 2
				y += 50
				dx = self.accuracy
				if dx < 0:
					x += dx
					dx = -dx
				self.screen.fill((255,0,0), (x,y,dx,3))
		for i in range(0,self.numkeys):
			if self.t - self.kjudgetime[i] > 300:
				self.kjudgement[i] = 0
			else:
				x = self.disprect.left + self.keystyle[i][0] + (self.keystyle[i+1][0] - self.keystyle[i][0] - 24) / 2
				y = self.disprect.bottom - 30
				if self.colmarkimg[self.kjudgement[i]]:
					self.screen.blit(self.colmarkimg[self.kjudgement[i]],(x,y))