# Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 24th of June, 2016

# importing needed modules
import pygame, sys, time, math, os, random, threading

""" CLASSES """
class Screen():
	def __init__(self):
		pass

	def swap(self):
		pass

	def render(self, surface):
		pass

	def tick(self):
		pass

	def handle(self, event):
		pass

class Button():
	def __init__(self, pos, color):
		self.pos = pos
		self.color = [0, 0, 0]
		self.destcolor = color

	def render(self, surface):
		pygame.draw.rect(surface, self.color, [self.pos[0], self.pos[1], 200, 200])

	def tick(self):
		for _ in [0, 1, 2]:
			self.color[_] += (self.destcolor[_] - self.color[_]) / 15.

	def activate(self):
		self.color = [255, 255, 255]

	def pressed(self, pos):
		if pos[0] >= self.pos[0] and pos[0] <= self.pos[0] + 200:
			if pos[1] >= self.pos[1] and pos[1] <= self.pos[1] + 200:
				return True

		return False

# game screeb
class mainScreen(Screen):
	def __init__(self):
		Screen.__init__(self)

		self.buttons = [
			Button([20, 20], [0, 255, 0]),
			Button([20+200+20, 20], [255, 0, 0]),
			Button([20, 20+200+20], [255, 255, 0]),
			Button([20+200+20, 20+200+20], [0, 0, 255])
		]

		self.reset()

	# reset game
	def reset(self):
		self.score = -1
		self.canclick = False
		self.sequence = []
		self.success = True

		self.showindex = 0
		self.showtimer = 20

		self.index = 0

		for b in self.buttons:
			b.color = [0, 0, 0]

	# tick
	def tick(self):
		# extend sequence and reset
		if self.success:
			self.score += 1
			self.canclick = False
			self.sequence.append(random.randint(0, 3))
			self.showindex = 0
			self.showtimer = 20
			self.success = False
			self.index = 0
		
		self.showtimer -= 1

		# activate a button
		if self.showtimer <= 0 and not self.canclick:
			self.showtimer = 20
			if self.showindex + 1 > len(self.sequence):
				self.canclick = True
			else:
				self.buttons[self.sequence[self.showindex]].activate()

			self.showindex += 1

		for b in self.buttons:
			b.tick()

	# handle
	def handle(self, event):
		if self.canclick:
			if event.type == pygame.MOUSEBUTTONDOWN:
				if event.button == 1:
					w = -1
					for b in self.buttons:
						w += 1
						if b.pressed(pygame.mouse.get_pos()):
							b.activate()


							if self.sequence[self.index] == w:
								
								self.index += 1
								if self.index + 1 > len(self.sequence):
									self.success = True
									
							else:
								self.reset()

	# render
	def render(self, surface):
		# render buttons
		for b in self.buttons:
			b.render(surface)

		# blit score
		s = segment7(self.score)
		r = s.get_rect()
		s = pygame.transform.scale(s, [r.right*10, r.bottom*10])
		r = s.get_rect()
		surface.blit(s, [(400 + 20*3 - r.right)/2, 400 + 20*3])

""" THREADS """
# thread class
class Thread(threading.Thread):
	def __init__(self):
		# init thread
		threading.Thread.__init__(self)
		
		# deamon thread
		#self.daemon = True

	# run function
	def run(self):
		pass

""" FUNCTIONS """
# validates a color integer
def colorValid(_color, _min = 0, _max = 255):
	newColor = math.fabs(_color)
	n = _max - _min
	if newColor > n:
		if int(newColor / n) % 2 == 0:
			newColor = newColor % n
		else:
			newColor = n - (newColor % n)
	
	return int(newColor) + _min

# gets the position on a circle
def getcirclepos(p, r, phi):
	return [p[0] + r * math.cos(phi * (math.pi/180.)), p[1] + r * math.sin(phi * (math.pi/180.))]

# returns an integer version of given position
def intpos(_pos):
	return [int(_pos[0]), int(_pos[1])]

# turn a number into 7-segment font
def segment7(number):
	number = str(number)

	segments = [
		[[1, 0], [2, 0]],
		[[3, 1], [3, 2]],
		[[3, 4], [3, 5]],
		[[1, 6], [2, 6]],
		[[0, 4], [0, 5]],
		[[0, 1], [0, 2]],
		[[1, 3], [2, 3]]
	]

	numbers = [
		[0, 1, 2, 3, 4, 5],
		[1, 2],
		[0, 1, 6, 4, 3],
		[0, 1, 6, 2, 3],
		[5, 6, 1, 2],
		[0, 5, 6, 2, 3],
		[0, 5, 6, 2, 3, 4],
		[0, 1, 2],
		[0, 1, 2, 3, 4, 5, 6],
		[0, 1, 6, 5, 2, 3]
	]

	surface = pygame.Surface([5*len(number)-1, 7])
	x = 0
	for digit in str(number):
		for n in numbers[int(digit)]:
			for s in segments[n]:
				surface.set_at([s[0] + x, s[1]], [255, 255, 255])

		x += 5

	return surface

""" GAME """
# game class
class Game():
	def __init__(self):
		# screen (class)
		self.screenname = "main"
		self.screens = {
			"main": mainScreen()
		}

		# screen (window)
		n = 400 + 20*3
		self.Width, self.Height = n, n + 100
		self.Size = [self.Width, self.Height]
		self.Screen = pygame.display.set_mode(self.Size)

		# running variables
		self.ticks = 0
		self.running = True

		# functions
		pygame.display.set_caption("Jimon")
	
	# further initialization
	def init(self):
		pass

	# get the screen based on name
	def screen(self):
		if self.screenname in self.screens:
			return self.screens[self.screenname]
		else:
			return Screen()

	# swao the current screen
	def swapscreen(self, name = ""):
		self.screenname = name
		self.screen().swap()

	# tick function
	def tick(self):
		# handle events
		for event in pygame.event.get():
			
			# quit when window is closed
			if event.type == pygame.QUIT:
				self.quit()

			# handle key presses
			if event.type == pygame.KEYDOWN:
				# F12 quits
				if event.key == pygame.K_F12:
					self.quit()

				# F1 screenshots
				if event.key == pygame.K_F1:
					self.screenshot()

			# handle screen
			self.screen().handle(event)

		# tick screen
		self.screen().tick()

	# render function
	def render(self):
		# fill
		self.Screen.fill([0, 0, 0])
		
		#render screen
		self.screen().render(self.Screen)
		
		# flip
		pygame.display.flip()
	
	# quits
	def quit(self):
		self.running = False

	# takes a screenshot
	def screenshot(self):
		# define path
		path = os.getcwd() + "/out/"
		
		# try to save
		try:
			# create path
			if not os.path.isdir(path):
				os.mkdir(path)
			
			# define name
			name = "img" + str(len(os.listdir(path))) + ".png"

			# save image
			pygame.image.save(self.Screen, path + name)
		
		# save failed somehow
		except:
			pass

	# run function (uses tick() and render())
	def run(self):
		ticksPerSecond = 60
		lastTime = time.time() * 1000000000
		nsPerTick =  1000000000.0 / float(ticksPerSecond)
	
		ticks = 0
		frames = 0
	
		lastTimer = time.time() * 1000
		delta = 0.0
		
		while self.running:
			now = time.time() * 1000000000
			delta += float(now - lastTime) / float(nsPerTick)
			lastTime = now
			shouldRender = False
					
			while delta >= 1:
				ticks += 1
				self.ticks += 1
				self.tick()
				delta -= 1
				shouldRender = True
			
			if shouldRender:
				frames += 1
				self.render()
			
			if time.time() * 1000 - lastTimer >= 1000:
				lastTimer += 1000
			
				frames = 0
				ticks = 0

# start game
G = Game()
G.init()
G.run()