# Original idea and Windows version "Parallel 2" by Yanis Batura
# Pygame technique taken from "Learnfast" program by Michal Wallace

# December 2005, Yann Le Du http://yledu.free.fr
# Second improved version

# 20/01/06 curv (Kio) Modified to fit on smaller screens,
# replaced string.rjust() with string.zfill(), changed default
# colours to be easier on the eyes. (Matter of opinion of course)

# Directions for use :
# Prerequisites : python, pygame, realplayer, Parallel 2 data files
# Unpack the windows Parallel 2 data files in a directory we'll call "Parallel"
# Put this program "parallel.py" in the directory "Parallel"
# Run it with python by typing "python parallel.py"


import os, string,time
import random, math, pygame
from pygame.locals import *
import pygame.mixer
import pygame.font
import pygame.key
import random

### globals ########################################################

WINSIZE = (790, 400)
CENTER = (WINSIZE[0]/2,WINSIZE[1]/2)

YELLOW = 255, 255,  0
BLACK = 0,     0,   0
CYAN = 0,   255,   255

TOPLINE, TOPLOWLINE, BOTTOMHIGHLINE,BOTTOMLINE = -2,-1,1,2
SEEN = []

### defs ###########################################################

def drawtext(screen, font, text, color, line):
    w,h = font.size(text)
    if line==TOPLINE:
        y = CENTER[1]-font.get_height()*2
    elif line==TOPLOWLINE:
        y = CENTER[1]-font.get_height()/2*1.7
    elif line==BOTTOMHIGHLINE:
        y = CENTER[1]+font.get_height()/2*1.7
    else:
        y = CENTER[1]+font.get_height()*2
    screen.blit(font.render(text, 0, color), (CENTER[0]-(w/2), y))


def init():
    pygame.init()
    screen = pygame.display.set_mode(WINSIZE)
    pygame.display.set_caption("Parallel")
    pygame.mixer.quit() # Free the sound device for realplayer
    return screen

def store():
    """
    Stores the English/Lojban examples for easy retrieval
    """
    level=""
    while level not in "0 1 2 3 4".split():
        print
        level = raw_input(" Which level do you want ? Choose a number between 0 and 4 (0 is pronunciation) : ")
    print

    if level == "0":
        datafile = "Lojban Pronunciation.txt"
        datadir = "Pronunciation"
    else:
        datafile="Lojban" + level.zfill(3) + "_Eng.txt"
        datadir = "Lojban_" + level.zfill(3)
        
    f=open(datafile,"r")
    total=f.readlines()
    f.close()

    counter=0
    symplus=False
    toplay=""
    working = total[1:]+["  "]
    timefortwo = .4
    if level == "0":
        timeforspace = 1.1
    else:
        timeforspace = .3

    storage=[] # Contains the English sentence and Lojban translation, it contains a series of "toadd", i.e. a series of examples

    # One "toadd" for each example Structure is :
    # [[1st English, 2nd English, etc.],[1st Lojban, 2nd Lojban, etc.],[wavfilename,time of play]]. An example may have multiple sentences, i.e. question+answer
    toadd=[[],[],[]]
    
    for el in working:
        if el[1]=="+":
            word = string.join(el[2:].split("\x00"),"").strip()
            if symplus: # In this case a Lojban answer to a question
                symplus = False
                toadd[1].append(word)
                much = sum([len(m)/2.*timefortwo for m in word.split(" ")])+word.count(" ")*timeforspace # Time for pronunciation
                toadd[2][1] += much # Add time for answer
            else: # In that case an English answer to a question
                symplus = True
                toadd[0].append(word)

        elif el[1]=="`": # In this case, we have the Lojban sentence
            counter=string.join(el.split("`")[1].split("\x00"),"").strip() # Voodoo for extracting Wav file number from unicode string
            toplay = datadir+os.sep+counter+".wav" # Wav file name

            word = string.join(el.split("`")[2].split("\x00"),"").strip() # Voodoo for extracting sentence from unicode string
            much = sum([len(m)/2.*timefortwo for m in word.split(" ")])+word.count(" ")*timeforspace # Time for pronunciation

            toadd[1].append(word)
            toadd[2].append(toplay)
            toadd[2].append(much)
            
        else: # In that case, we have the English sentence
            storage.append(toadd) # We have a new English example, so we store the previous one...
            toadd=[[],[],[]] # and a new example begins
            word = string.join(el.split("\x00"),"").strip()
            toadd[0].append(word)

    return storage[1:],level
    

def main(storage,level):

    automatise=""
    while automatise not in ("M " + ("G ") * (level != "0") + "S").split():
        m = "\n\t M -> MANUAL (press key for next/previous example and translation)"
        g = "\n\t G -> GUESS (examples given RANDOMLY one after the other with short delay between Enlgish and Lojban displays to find translation)" * (level != "0")
        s = "\n\t S -> SCROLLING (examples given RANDOMLY one after the other with English/Lojban displayed simultaneously)"
        automatise = raw_input(" Choose :" + m + g + s + "\n\n\t Choice ? ")
        automatise = string.upper(automatise)
    print
    print

    screen = init()
    font = pygame.font.Font(None, 30)

    tick, tock = YELLOW, BLACK
    this, next = tick, tock

    numexamples = len(storage)
    poslist = range(numexamples) # List of examples' positions
    

    pos = 0
    choice="zulu"
    numex=0
    while choice != "Q":
        if automatise != "M":
            if poslist == []:
                break
            numex += 1
            pos = random.randrange(len(poslist)) # Random example for Learning and Scrolling mode
            el = storage[poslist[pos]]
            poslist.pop(pos) # Remove the index of the example drawn
        else:
            numex = pos+1 # If automatise != "M" pos and poslist[pos] are equal
            el = storage[pos]
            

        screen.fill(BLACK)

        pygame.display.set_caption("Parallel - Level " + level + " - Example number " + str(numex) + "/" + str(numexamples))
        drawtext(screen, font, el[0][0], YELLOW, TOPLINE)
        pygame.display.flip()
        if len(el[0])==2:
            drawtext(screen, font, el[0][1], YELLOW, BOTTOMHIGHLINE)
            pygame.display.flip()
            
        if automatise == "M":
            p = " \n\t P + Enter \t\t-> previous example" * (pos > 0)
            n = " \n\t Spacebar + Enter \t-> next example" * (pos < numexamples-1)
            choice = "zulu"
            while choice not in ("; " + ";N"*(pos < numexamples-1) + ";P"*(pos > 0) + ";Q").split(";"):
                choice = string.upper(raw_input(" Choose : \n\t Enter \t\t\t-> Lojbanize this example" + n + p + " \n\t Q + Enter\t\t-> quit \n\n\t Choice ? "))
            print
            if choice == "Q":
                continue
            elif choice == " " and n != "":
                pos+=1
                continue
            elif choice == "P" and p != "":
                pos-=1
                continue
            else:
                pass
            
        elif automatise == "G":
            if level != "0":
                time.sleep(el[2][1])
            else:
                pass
            
        drawtext(screen, font, el[1][0], CYAN, TOPLOWLINE)
        pygame.display.flip()
        if len(el[1])==2:
            drawtext(screen, font, el[1][1], CYAN, BOTTOMLINE)
            pygame.display.flip()                

        if automatise == "M":
            p = " \n\t P + Enter \t\t-> previous example" * (pos > 0)
            n = " \n\t Spacebar + Enter \t-> next example" * (pos < numexamples-1)
            h = " \n\t Enter \t\t\t-> hear the Lojban translation of the current example"
            while True:
                choice = "zulu"
                while choice not in ("; " + ";N"*(pos < numexamples-1) + ";P"*(pos > 0) + ";Q; ").split(";"):
                    choice = string.upper(raw_input("\n Press" + h + n + p + " \n\t Q + Enter\t\t-> quit \n\n\t Choice ? "))
                print
                
                if choice == "Q":
                    break
                elif choice == " " and n != "":
                    pos+=1
                    choice = "zulu"
                    break
                elif choice == "P" and p != "":
                    pos-=1
                    choice = "zulu"
                    break
                elif choice == "":
                    os.system("realplay "+el[2][0]+" &") # Play the wav
        else:
            os.system("realplay "+el[2][0]+" &") # Play the wav
            time.sleep(el[2][1])
                

if __name__=="__main__":
    
    storage,level=store()
    main(storage,level)
