# Pyntor::Slides - Display slides
# -*- coding: utf-8 -*-
# Copyright (C) 2004-2006 Josef Spillner <josef@coolprojects.org>
# Published under GNU GPL conditions

import pygame
from pygame.locals import *
import sys
import time
import random
import os, pwd
import re

class Slides:
	def init(self, options):
		slideshow = options["slides"]

		option = options["pages"]
		if option.find("-") >= 0:
			(start, stop) = option.split("-")
			self.readslide = int(start)
			self.lastslide = int(stop)
		else:
			self.readslide = int(option)
			self.lastslide = -1

		self.blackheading = options["inverse"]

		f = open(slideshow)
		blines = f.readlines()
		f.close()
		self.lines = []
		for line in blines:
			self.lines.append(unicode(line.rstrip(), "utf-8"))

		self.fulltext = {}
		self.headings = {}

		counter = 0
		oldline = ""
		useoldline = None
		for l in self.lines:
			savetext = 0
			if counter >= self.readslide:
				savetext += 1
			if counter <= self.lastslide or self.lastslide == -1:
				savetext += 1
			if savetext == 2:
				xcounter = counter - self.readslide + 1
				#print options, "::", xcounter, self.readslide, self.lastslide
				if not self.fulltext.has_key(xcounter):
					self.fulltext[xcounter] = []
				self.fulltext[xcounter].append(l)
				if useoldline:
					self.fulltext[xcounter].append(useoldline)
					self.headings[xcounter] = useoldline
					useoldline = 0
			if l.find("======") == 0:
				counter = 1
				useoldline = oldline
			if l.find("-----") == 0:
				counter += 1
				useoldline = oldline
			oldline = l

		#print "COUNTER", counter, self.readslide, self.lastslide
		if self.lastslide != -1:
			if self.lastslide < counter:
				counter = self.lastslide
		if self.readslide != 1:
			counter -= self.readslide
			counter += 1
		#print "COUNTER-new", counter

		self.pages = counter

	def render(self, screen, page, globalpage):
		#screen = pygame.display.get_surface()

#		screenorig = pygame.Surface((screen.get_width(), screen.get_height()))
#		screenorig.blit(screen, (0, 0))

#		white = pygame.Surface((screen.get_width(), screen.get_height()))
#		white.fill((255, 255, 255))
#		#alphapart = 160
#		alphapart = 0

#		screencopy = pygame.Surface((screen.get_width(), screen.get_height()))
#		screencopy.blit(screen, (0, 0))
#		screencopy2 = pygame.Surface((screen.get_width(), screen.get_height()))
#		screencopy2.blit(screen, (0, 0))

		surface = pygame.Surface((screen.get_width(), screen.get_height()))
		surface.blit(screen, (0, 0))

		titlefont = pygame.font.SysFont("Vera Sans", 40)
		bigfont = pygame.font.SysFont("Vera Sans", 42)
		smallfont = pygame.font.SysFont("Vera Sans", 24)
		verysmallfont = pygame.font.SysFont("Vera Sans", 18)
		smallfontmath = pygame.font.SysFont("Cmsy10", 26)

		# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx
		# RENDER HERE!

		heading = ""
		subheading = ""
		pageheading = ""
		counter = 0
		rawmode = 0
		rawlist = []
		eventlist = {}

		# FIXME: abandon readslide
		readslide = self.readslide + page - 1
		#print "RENDER", page, "WHICH IS", readslide

		oldline = ""
		for l in self.lines:
			if l.find("======") == 0:
				heading = oldline
				counter = 1
			if oldline.find("======") == 0:
				subheading = l
			if readslide > 1 or readslide == 1:
				if l.find("-----") == 0:
					counter += 1
					if counter == readslide:
						pageheading = oldline
						rawmode = 1
					else:
						rawmode = 0
			oldline = l

			if rawmode == 1:
				rawlist.append(l)

#		if readslide != oldslide:
#			surface.blit(screencopy, (0, 0))
#			screencopy2.blit(screencopy, (0, 0))
#		else:
#			surface.blit(screencopy2, (0, 0))

		if readslide == 1 and heading is not "":
			f = titlefont.render(heading, 1, (0, 120, 255))
			surface.blit(f, ((surface.get_width() - f.get_width()) / 2, 200))
			f = smallfont.render(subheading, 1, (255, 255, 255))
			surface.blit(f, ((surface.get_width() - f.get_width()) / 2, 300))
		else:
			if len(rawlist) == 0:
				return
			if readslide == self.lastslide + 1:
				return

			if self.blackheading:
				#f = bigfont.render(pageheading, 1, (255, 255, 255))
				f = bigfont.render(pageheading, 1, (200, 200, 100))
			else:
				f = bigfont.render(pageheading, 1, (0, 120, 255))
			surface.blit(f, (60, 25))

			i = 0
			xmarker = 0
			rawlist.pop()
			rawlist.pop(0)
			for l in rawlist:
				reimg = re.compile("\[img:(\S+)\]")
				mimg = reimg.match(l)
				recimg = re.compile("\[cimg:(\S+)\]")
				mcimg = recimg.match(l)
				reurl = re.compile("\[url:(\S+)\]")
				murl = reurl.match(l)
				reexec = re.compile("\[exec:(\S+)\]")
				mexec = reexec.match(l)
				if mimg:
					img = mimg.group(1)
					pic = pygame.image.load(img)
					surface.blit(pic, (60, 100 + i * 30))
					i += pic.get_height() / 30 + 1
				elif mcimg:
					img = mcimg.group(1)
					pic = pygame.image.load(img)
					xpos = (surface.get_width() - pic.get_width()) / 2
					ypos = (surface.get_height() - pic.get_height()) / 2
					surface.blit(pic, (xpos, ypos))
					#i += pic.get_height() / 30 + 1
				elif murl:
					url = murl.group(1)
					smallfont.set_italic(1)
					f = smallfont.render(url, 1, (0, 0, 150))
					smallfont.set_italic(0)
					surface.blit(f, (60, 100 + i * 30))
					eventlist[i] = url
					i += 1
				elif mexec:
					execurl = mexec.group(1)
					lmod = re.sub(reexec, execurl, l)
					smallfont.set_italic(1)
					f = smallfont.render(lmod, 1, (0, 0, 0))
					surface.blit(f, (60, 100 + i * 30))
					f = smallfont.render(execurl, 1, (0, 150, 150))
					smallfont.set_italic(0)
					surface.blit(f, (60, 100 + i * 30))
					eventlist[i] = execurl
					i += 1
				else:
					## begin math
					rmath = re.compile("(?P<exp>\[math:(?P<term>\w+)\])")
					while 1:
						mmath = rmath.search(l)
						if mmath:
							print mmath.groupdict()
							print "STRING", l
							print "SYM", mmath.group("term")
							print "MATCH", mmath.start("exp"), mmath.end("exp")
							sym = mmath.group("term")
							font = smallfontmath
							offset = 6
							if sym == "diamond":
								sym = u"◊" # Attention: diamond, not space
								font = smallfont
								offset = 0
							f = font.render(sym, 1, (255, 255, 255))
							l = l[:mmath.start("exp")] + "  " + l[mmath.end("exp"):]
							ltmp = l[:mmath.start("exp")]
							ftmp = smallfont.render(ltmp, 1, (255, 255, 255))
							w = ftmp.get_width()
							surface.blit(f, (60 + w, 100 + i * 30 + offset))
						else:
							break
					## end math

					#if len(l) == 0 or l[0] != " ":
					#	xmarker = 0
					#if marker == -1 or marker == i:
					#	xmarker = 1
#					if marker == -1 or marker == i or xmarker:
#						f = smallfont.render(l, 1, (255, 255, 100))
#					else:
					f = smallfont.render(l, 1, (255, 255, 255))
					#f = smallfont.render(l, 1, (200, 200, 100))
					surface.blit(f, (60, 100 + i * 30))

					i += 1

			xpage = globalpage
			if self.blackheading:
				#f = verysmallfont.render(subheading + " (" + str(xpage) + ")", 1, (255, 255, 255))
				f = verysmallfont.render(subheading + " (" + str(xpage) + ")", 1, (200, 200, 100))
			else:
				f = verysmallfont.render(subheading + " (" + str(xpage) + ")", 1, (0, 120, 255))
			surface.blit(f, (50, 704))

		oldslide = readslide
		readslide = 0

		screen.blit(surface, (0, 0))
		#pygame.display.flip()


		# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx

#		oldslide = 0
#		marker = -1
#		mouse = 0
#		draw = 0
#		dodraw = 0
#		posx = 0
#		posy = 0
#		dirty = 0

#		eventlist = {}

		#readslide = 1

#		screen.blit(screencopy, (0, 0))

	# RETURN codes:
	# "exit", "next", "previous"

	def interactive(self, event):
		if event.type == KEYDOWN:
			key = event.key
			if key == K_ESCAPE or pygame.event.peek(QUIT):
				return "exit"
			if key == K_RETURN:
				return "next"
			if key == K_BACKSPACE:
				return "previous"
			#if key == K_f:
			#	mouse = 1 - mouse
			#	pygame.mouse.set_visible(mouse)
			#	pygame.display.toggle_fullscreen()
			#if key == K_m:
				#mouse = 1 - mouse
				#pygame.mouse.set_visible(mouse)
			#if key == K_s:
				#try:
				#	os.mkdir("static")
				#except:
				#	pass
				#filename = "slide" + str(oldslide) + ".bmp"
				#pygame.image.save(screen, os.path.join("static", filename))
			#if key == K_PLUS:
				#alphapart += 15
				#white.set_alpha(alphapart)
				#screencopy.blit(screenorig, (0, 0))
				#screencopy.blit(white, (0, 0))
				#screencopy2.blit(screenorig, (0, 0))
				#screencopy2.blit(white, (0, 0))
				#readslide = oldslide
			#if key == K_MINUS:
				#alphapart -= 15
				#white.set_alpha(alphapart)
				#screencopy.blit(screenorig, (0, 0))
				#screencopy.blit(white, (0, 0))
				#screencopy2.blit(screenorig, (0, 0))
				#screencopy2.blit(white, (0, 0))
				#readslide = oldslide
			#if key == K_DOWN:
			#	marker += 1
				#readslide = oldslide
			#if key == K_UP:
			#	marker -= 1
				#readslide = oldslide

		# FIXME!
		mouse = 0

		if mouse:
			if event.type == MOUSEBUTTONDOWN:
				draw = 1
				dodraw = 0
				(posx, posy) = event.pos
				line = (posy - 100) / 30
				if self.eventlist.has_key(line):
					if self.eventlist[line].find("http") >= 0:
						os.spawnlp(os.P_NOWAIT, "konqueror", "konqueror", self.eventlist[line])
					else:
						os.spawnlp(os.P_NOWAIT, self.eventlist[line], self.eventlist[line])
			if event.type == MOUSEBUTTONUP:
				draw = 0
				dirty = 1
			if event.type == MOUSEMOTION:
				(posx, posy) = event.pos
				dodraw = 1

#		if draw:
#			if dodraw:
#				#screencopy2.fill((255, 100, 0), ((posx, posy), (20, 20)))
#				pass # XXX
#		if dirty:
#			dirty = 0
#			readslide = oldslide

component = Slides()

parameters = (
	("slides", "Filename which refers to slides file", None),
	("pages", "Initial page number (x) or range (x-y) to use", "1"),
	("inverse", "Whether to invert colours", 0)
)

metainfo = {
	"version": "0.2",
	"author": "Josef Spillner",
	"authoremail": "<josef@coolprojects.org>",
	"licence": "GPL"
}

doc = """
Slides: Default slideshow component with wiki-like syntax

Slides can display text with highlighting for URLs via [url:xxx] tags.
It supports some mathematical expressions such as \\diamond, embedded
images via [img:xxx], and program execution via [exec:xxx] tags.
Images can be displayed centered with the [cimg:xxx] tag.

Usage: 'slides' -slides <slidefile> [-pages <n|n-m>] [-inverse true]
 Where <slidefile> is the file containing the presentation markup text

Display: yes

Interactivity: switching pages with enter/backspace
               launching web browser with clicks on hyperlinks
"""

