# -*- coding: utf-8 -*-

# Copyright (c) 2006 Stas Zykiewicz <stas.zytkiewicz@gmail.com>
#
#           findsound.py
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public License
# as published by the Free Software Foundation.  A copy of this license should
# be included in the file GPL-2.
#
# 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 Library 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

## findsound a game where you see a bunch of images and then you hear a sound.
## select the image which belongs to the sound.
## Age 3-5


RCFILE = 0
_FSDEBUG = 0

import os,sys,random,glob
import pygame
from pygame.constants import *
from utils import load_image,load_music,trace_error,char2surf,MyError,get_locale
from SpriteUtils import CPSprite,CPGroup,CPinit
from CPMenu import MenuItem


class Img:
    """ Container to store image objects"""
    pass
class Snd:
    """ Container to store sound objects"""
    pass
class Misc:
    """ Container to store all kind of stuff"""
    pass
NOSOUNDTXT = """It seems that we cannot use the sound card right now and because this game
  is all about sound, we just quit.
  This problem can also be caused by another application which uses the
  soundcard right now."""

class Button(MenuItem):
    def __init__(self,img,pos,data):
        MenuItem.__init__(self,img,pos,data)
    
        
class ImageObject(CPSprite):
    def __init__(self,img,snd):
        CPSprite.__init__(self)
        self.image = img
        self.rect = self.image.get_rect()
        self.sound = snd
        self.connect_callback(self.callback, event_type=MOUSEBUTTONDOWN)
        
    def set_position(self,pos):
        self.rect.move_ip(pos)
    
    def play(self):
        load_music(self.sound).play(1)
        
    def callback(self,*args):
        """If this is called the user hits the right image."""
        self.erase_sprite()
        return 10#the score

class Game(Img,Snd):    
    """  Findsound - part of childsplay.py, a suite of educational games for
  young children. """
    
    def __init__(self,screen,backgr,rc_dic,basepath,libdir,cpg):
        self.screen = screen
        self.backgr = backgr
        Img.screen = self.screen
        Img.backgr = self.backgr
        self.rc_dic = rc_dic
        self.basedir  = basepath
        self.libdir = libdir
        self.gamelevels =('level1','level2','level3')
        self.gameitems = [None]
        Misc.actives = CPinit(self.screen,self.backgr)# mandatory when using anything from the SpriteUtils
        self._setup()
        
    def __del__(self):
        pass
            
    def _setup(self):
        """ Set all the stuff we need"""
        self.sounddir = os.path.join(self.libdir,'FindsoundData','Sounds')
        self.imagedir = os.path.join(self.libdir,'FindsoundData','Images')
        img = load_image(os.path.join\
                        (self.libdir,'FindsoundData','Data','soundbut.png'),1)
        
        back = load_image(os.path.join\
                        (self.libdir,'FindsoundData','Data','back.jpg'),0)
        self.backgr.blit(back,(0,0))
        self.screen.blit(back,(0,0))
        pygame.display.update()
        pos = (350,400)
        self.soundbutton = Button(img,pos,1)
        
    def start(self,level,item):
        """Listen to the sound and find the image to which it belongs. """
        Sdir = os.path.join(self.sounddir,level)
        Idir = os.path.join(self.imagedir,level,'*.png')
        objects = []
        self.stop = 0
        y_offset,x_offset,maxcol = 140,100,3
        for file in glob.glob(Idir):
            img = load_image(file,1)
            root, ext = os.path.splitext(os.path.basename(file))
            snd = os.path.join(Sdir,root+'.ogg')
            if _FSDEBUG: print "img,snd",file,snd
            objects.append(ImageObject(img,snd))
        if _FSDEBUG: print "objects",objects
        if not pygame.mixer.get_init():
            MyError.name = str(self)
            MyError.extra = NOSOUNDTXT
            raise MyError
        random.shuffle(objects)
        rows,cols = divmod(len(objects),maxcol)
        rows += (rows == 0 or cols != 0)
        if _FSDEBUG: print "rows,cols",rows,cols
        y = 40
        x = 10
        self.objects = []
        for row in range(0,rows):
            x = 0
            for col in range(0,maxcol):
                x += x_offset
                try:
                    obj = objects.pop()
                    obj.set_position((x,y))
                except IndexError:
                    break
                else:
                    if _FSDEBUG: print "object position",x,y
                    obj.display_sprite()
                    self.objects.append(obj)
                    x += obj.image.get_width()
            y += y_offset
        random.shuffle(self.objects)
        if _FSDEBUG: print "self.objects",self.objects
        self.selected_object = self.objects.pop()
        self.selected_object.play()
        self.soundbutton.display_sprite()
    
    def picked_object(self):
        try:
            self.selected_object = self.objects.pop()
        except IndexError:
            self.stop = -1
        else:
            self.selected_object.play()
    
    def __str__(self):
        """Must return the original, not translated, title of this game.
        It's needed by the high score class of childsplay."""        
        return "Findsound"

    def helptitle(self):
        return _("Findsound")
    
    def help(self):
        text = [_("The aim of the game:"),
        _("Listen to the sound and click on the image to which it belongs."),
        " ",
        _("Difficulty : 3-5 years"),
        " ",
        _("Number of levels : 3")]
        return text
 
    def loop(self,events):
        item,Misc.score = None,0
        for event in events:
            if event.type is MOUSEBUTTONDOWN:
                item=event
                break
        try:
            v = self.selected_object.update(item)
            if v:
                Misc.score = v
                self.picked_object()
            v = self.soundbutton.update(item)
            if v:
                self.selected_object.play()
        except:
            print trace_error()
            sys.exit(1)
        return self.stop,Misc.score
