#~ /***************************************************************************
 #~ *            letters.py
 #~ *
 #~ *  Thu Oct 21 17:20:22 2004
 #~ *  Copyright  2004  Stas Z
 #~ *  stas@linux.isbeter.nl
 #~ ****************************************************************************/
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, write to the Free Software Foundation,
# 675 Mass Ave, Cambridge, MA 02139, USA.
#

RCFILE = 0
DEBUG = 0
import os,sys,random,operator,fnmatch,gettext
import pygame
from pygame.constants import *
from CPConstants import DATADIR

from utils import load_image,load_sound,font2surf,MyError,ChildsplayGoodies
try:
    import pyassetml,pyassetmlSDL
except (ImportError,MyError),info:
    print >> sys.stderr,info,"\nThis version of childsplay depends on pyassetml(SDL)"
    text = "Module letters fails to import pyassetml(SDL)"
    raise MyError,text

class Img:
    pass
class Snd:
    pass

class Arrow:
    def __init__(self,start,end):
        self.image = Img.arrow
        self.rect = self.image.get_rect()
        self.move = 6
        self.zone = pygame.Rect(start + (self.rect[3],) + (end,))
        self.rect.move_ip(start)
                
    def update(self):
        self.rect = self.rect.move(0,self.move)
        if not self.zone.contains(self.rect):
            self.move = -self.move
    def erase(self):
        self.rect = Img.screen.blit(Img.backgr,self.rect,self.rect)
        
class Game(Img,Snd):    
    """  Letters.py - part of childsplay.py, a suite of educational games for
  young children.
  """

    def __init__(self,screen,backgr,rc_dic,basepath,libdir):
        Img.screen = screen
        Img.backgr = backgr
        self.gamelevels = range(1,5)
        self.gameitems = range(4)
        self.rc_dic = rc_dic
        self.basedir  = basepath
        self.libdir = libdir
        self.stop = 0
        self.score = 0
        if DEBUG: print "ChildsplayGoodies",dir(ChildsplayGoodies)       
        # create two assetmlSDL instances one for parsing images and one for sounds
        self.Assets_img = pyassetmlSDL.AssetmlSDL()
        self.Assets_img.set_mldir('childsplay/childsplay-images/childsplay-images.assetml')
        Img.arrow = self.Assets_img.get_assets(('arrow.png',))
        # get pictures
        self.Assets_img.set_mldir('childsplay/memory-136x136/memory-136x136.assetml')
        descr_pics = self.Assets_img.get_assets(('*.png',),fullname=1)# {foo.png:foo.png object,spam.png:spam.png object}
        
        parser = pyassetml.AssetmlParser('childsplay/memory-136x136/memory-136x136.assetml')       
        loc = ChildsplayGoodies.language
        if DEBUG: print "letters game, locale set to",loc
        #if os.name == 'nt': # we don't have langauge support (gettext)
        #    loc = 'en'
        if loc == 'system': loc = 'en'
        self.trans_descr_pics = {}
        for k,v in descr_pics.items():
            try:
                found = parser.find_names((('file',k),('description',loc)))[0]
            except TypeError:
                if DEBUG: print >> sys.stderr,"Error in names searching, assetml","descr_pics",descr_pics,"locale",loc
                found = None
            if found:
                self.trans_descr_pics[found.upper()] = v
                if DEBUG: print "Found localized words ",found
            else:
                self.trans_descr_pics[k.upper()[:-4]] = v
                if DEBUG: print "Found words",k
        
        self.Assets_snd = pyassetmlSDL.AssetmlSDL()
        self.Assets_snd.set_mldir('childsplay/childsplay-sounds/childsplay-sounds.assetml')
        files = ('bummer.wav','wahoo.wav')
        self.Assets_snd.get_assets(files, Snd)
         
        self._setup()   
        
    def _setup(self):
        self.ttf = os.path.join(DATADIR,'bluebold.ttf')
        self.score = 0
        self.fontsize = 100
        self.fcol = (226,178,31)
                
        wrdlist = self.trans_descr_pics.keys()
        random.shuffle(wrdlist)
        
        self.wordlist = wrdlist[:]
        if DEBUG: print "wordlist",self.wordlist
        self.objs_to_move = []
        
        self.piccoor = (300,40)
    
    def start(self,level,i):
        """  Type the letter under the arrow,or type the whole word""" 
        
        word = self.wordlist[i]
        if DEBUG: print "Choosen word",word
        
        self.word = word # use standard
        self.wordpic = self.trans_descr_pics[self.word]
        
        try:
            spam,self.sizelist =  font2surf(self.word,self.fontsize,self.fcol,self.ttf)
        except MyError,info:
            MyError.line = 'method start()'
            MyError.name = __name__
            raise MyError,info
        l = 0
        for item in self.sizelist: # count the letter size
            l = l+item[0]
        if l >= 350:
            self.fontsize = self.fontsize - 20
            l = 350
        self.userword = u""
        self.wordcoor = (400-l-50,340)
        self.usercoor = (self.wordcoor[0]+l+50,340)
        box = pygame.Rect(self.usercoor + (l,item[1]))
        box.inflate_ip(4,4)
        br = pygame.draw.rect(self.screen,(9,244,9),box,2)
        # pythonish case in :)
        apply({"1":self._level_1,
            "2":self._level_2,
            "3":self._level_3,
            "4":self._level_4}[str(level)])
        
        r = Img.screen.blit(self.wordsurf,self.wordcoor)
        rr = Img.screen.blit(self.wordpic,self.piccoor)
        pygame.display.update((r,rr,br))
        
    def _level_1(self):
        self.end = 140
        self.objs_to_move.append((Arrow((self.wordcoor[0],self.wordcoor[1]-132),self.end)))
        self.offset = self.wordcoor[0]
        self.wordsurf,spam =  font2surf(self.word,self.fontsize,self.fcol,self.ttf)
        self.arrowdic = {} # used to store the coord. of the letters
        map(operator.setitem,[self.arrowdic]*len(self.sizelist),self.word,self.sizelist)
        
    def _level_2(self):
        self.piccoor = (300,100)
        pick = random.choice(self.word)
        wrd = self.word.replace(pick,'-',1)
        self.wordsurf,spam =  font2surf(wrd,self.fontsize,self.fcol,self.ttf)
    
    def _level_3(self):
        dash = '-'*(len(self.word)-2)
        wrd = self.word[0]+dash+self.word[-1]
        self.wordsurf,spam =  font2surf(wrd,self.fontsize,self.fcol,self.ttf)
        
    def _level_4(self):
        wrd = '-' * len(self.word)
        self.wordsurf,spam =  font2surf(wrd,self.fontsize,self.fcol,self.ttf)
    
    def loop(self,events):
        self.dirty_rects = []
        self.score = 0
        self.stop = 0
        for event in events:
            if event.type is KEYDOWN and 96<event.key<123 :
                userkey = event.unicode
                #print userkey
                self._check_key(userkey[0])# when multiple keyes are pushed, len(userkey) > 1 ???
            # XXX implement shift keys ???
            #elif event.type is KEYDOWN and event.key K_RSHIFT or event.key is K_LSHIFT
        for obj in self.objs_to_move:
            self.dirty_rects.append((Img.screen.blit(Img.backgr,obj.rect,obj.rect)))
            obj.update()
            self.dirty_rects.append((Img.screen.blit(obj.image,obj.rect)))
        pygame.display.update(self.dirty_rects)
        return self.stop,self.score
    
    def __str__(self):
        """Must return the original, not translated, title of this game.
        It's needed by the high score class of childsplay."""        
        return "Letters"
    
    def helptitle(self):
        return _('Letters')
        
    def help(self):
        text = [_("The aim of the game:"),
        _("Learning to type simple words with examples and pictures."),
        " ",
        _("Difficulty : 4-6 years"),
        _("Number of levels : 4"),
        " ",
        _("Try to type the letters and words, there are four levels each one"),
        _("slightly more difficult then the previous one."),
        _("In every level there are one or more letters left out of the word."),
        _("The last level just shows you the picture and dashes."),
        _("If you hit a wrong letter you hear a 'bummer' sound."),
        _("You can try as many times until you hit the right letter (26 times?)."),
        " ",
        _("Translation of the words:"),
        _("If you installed childsplay with the provided 'Makefile',"),
        _("you have had the opportunity to translate the words used by"),
        _("the letters module."),
        _("and type 'letters-trans.py' (without the ' ')."),
        _("If you get a 'bash: letters-trans.py: command not found' error you"),
        _("should look where letters-trans.py is installed and run it from there.")]

        return text
        
    
    def _check_key(self,key):
        key = unicode(key.upper())
        step = len(self.userword)
        #print 'step',step,self.word[step]
        if self.word[step] == key:
            self.userword = "%s%s" % (self.userword,key)
            if self.userword == self.word:
                self._blit_key(self.userword,step)
                self._word_complete() # We don't return
            else:
                self._blit_key(self.userword,step)
                self.score = 1
                if len(self.objs_to_move) > 0: # erase arrow
                    obj = self.objs_to_move.pop()
                    obj.erase()
                    self.dirty_rects.append((obj.rect))
                    # create new arrow
                    x = self.arrowdic[key][0] + self.offset
                    y = self.wordcoor[1]-132
                    self.objs_to_move.append((Arrow((x,y),self.end)))
                    self.offset = x
        else:
            self.score = -1
            Snd.bummer.play(1)
        return 0
    
    def _blit_key(self,seq,step):
        seqsurf,spam = font2surf(seq,self.fontsize,self.fcol,self.ttf)
        rec = seqsurf.get_rect()
        rec.move_ip(self.usercoor)
        old = self.screen.blit(Img.backgr,rec,rec)
        new = self.screen.blit(seqsurf,rec)
        pygame.display.update([old,new])
        
    def _word_complete(self):
        if len(self.objs_to_move) > 0: #erase arrow
            obj = self.objs_to_move.pop()
            obj.erase()
            self.dirty_rects.append((obj.rect))
        #print 'complete word'
        Snd.wahoo.play()
        self.score += 20
        self.stop = -1
