#!/usr/bin/python2.5
# -*- coding: utf-8 -*-
# Sayhoo: an audio navigation help for velib' like projects.
# Copyright 2008 Pierre Amadio
# pierre.amadio@libertysurf.fr
#
# 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 version 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 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
import sys
sys.path.append("/usr/share/sayhoo/python")
import Queue
import threading
import time
from  sayhooGlobals import *
from sayhooGlobals import _ 
try:
    import sqlite3
except:
    from pysqlite2 import dbapi2 as sqlite3

import signal

if is_maemo():
    import gpsbt

import locale
import os

""" While there are some problemes with gettext"""
#locale.setlocale(locale.LC_ALL, "en_GB")
#os.environ["LANGUAGE"]="en_GB"


#import gtk.glade
#import gettext
#import sys
#import locale
#import os
#import hildon

"""
from gnome import gconf
#from gnome import gnomevfs

import datetime
import sqlite3
import re
import pango
import gobject
#import gst,pygst
import gpsbt
import math

"""



class EventManager:
    """this object is responsible for coordinating most communication
    between the Model, View, and Controller.
    """
    def __init__(self ):
        from weakref import WeakKeyDictionary
        self.listeners = WeakKeyDictionary()

    #----------------------------------------------------------------------
    def register_listener( self, listener ):
        self.listeners[ listener ] = 1

    #----------------------------------------------------------------------
    def unregister_listerner( self, listener ):
        if listener in self.listeners.keys():
            del self.listeners[ listener ]

    #----------------------------------------------------------------------
    def post( self, event ):
        """Post a new event.  It will be broadcast to all listeners"""
        for listener in self.listeners.keys():
            #NOTE: If the weakref has died, it will be 
            #automatically removed, so we don't have 
            #to worry about it.
            listener.notify( event )

        return True

    def fetch(self):
        """Fetch event coming from the controller themeself"""
        for listener in self.listeners.keys():
            for event in listener.get_requested_event():
                self.post(event)
        


class Controller:
    def __init__(self):
        return

    def notify(self):
        print "notify should be done in subclasses"

    def get_requested_event(self):
        print "get_requested event should be implemented in a subclass"
        return []
        
class GuiController(Controller):
    def __init__(self):
        Controller.__init__(self)
        import sayhooGui
        self.qq_to_gui=Queue.Queue()
        self.qq_from_gui=Queue.Queue()
        self.gui=sayhooGui.SayhooGui(self.qq_to_gui,self.qq_from_gui)
        self.event_to_request=[]


    def pull_request(self):
        #print "pull_requ"
        out=[]
        while self.qq_from_gui.qsize():
            try:
                ev=self.qq_from_gui.get(False,30)
                out.append(ev)
            except:
                raise
            
        return out


    def treat_request(self,req):
        if req.args['type']=="list_velib_stations":
            sql_db=sqlite3.connect(db_location)
            cursor=sql_db.cursor()
            snt="select id_station,lat,lon,label from velibs"
            cursor.execute(snt)
            answer=GuiAnswer(args=req.args,answer=cursor.fetchall())
            sql_db.close()
            self.qq_to_gui.put(answer)

        if req.args['type']=='new_destination':
            ev=MapRequest(args=req.args)
            self.event_to_request.append(ev)
         
        if req.args['type']=='new_start_point':
            #print "treat request: new start point"
            ev=MapRequest(args=req.args)
            self.event_to_request.append(ev)

        if req.args['type']=='new_location':
            """making a fake gps event"""
            print "fake gps event",req
            self.event_to_request.append(req)
   
    def notify(self,event):
        if isinstance( event, TickEvent ):
            for req in self.pull_request():
                self.treat_request(req)
            
        if isinstance(event,StartEvent):
            self.qq_to_gui.put(event)

        if isinstance(event,MapAnswer):
            if event.args["type"]=="route-found":
                self.qq_to_gui.put(event)
            
            if event.args["type"]=="new-destination-node":
                self.qq_to_gui.put(event)
            
            if event.args["type"]=="new-start-node":
                self.qq_to_gui.put(event)

        if isinstance(event,MapRequest):
            if event.args['type']=="map-computing":
                self.qq_to_gui.put(event)

        if isinstance(event,GpsEvent):
            if event.args["type"]=="new_location":
                self.qq_to_gui.put(event)

        

        return True

    def get_requested_event(self):
        out=[]
        while len(self.event_to_request):
            out.append(self.event_to_request.pop(0))
        return out



class MapController(Controller):
    def __init__(self):
        Controller.__init__(self)        
        import sayhooMap
        self.qq_to_router=Queue.Queue()
        self.qq_from_router=Queue.Queue()
        self.router=sayhooMap.sayhooRouter(self.qq_to_router,self.qq_from_router)
        self.event_to_request=[]

        return

    def pull_request(self):
        out=[]
        while self.qq_from_router.qsize():
            try:
                ev=self.qq_from_router.get(False,30)
                out.append(ev)
            except:
                raise
            
        return out
    
    def treat_request(self,req):
        #print "a request to be treaded in MapController",req
        #print req.args
        #print req.answer
        if isinstance(req,MapAnswer):
            if req.args["type"]=="route-found":
                self.event_to_request.append(req)
            if req.args["type"]=="new-destination-node":
                self.event_to_request.append(req)
            if req.args["type"]=="new-start-node":
                self.event_to_request.append(req)
        if isinstance(req,MapRequest):
            if req.args['type']=="map-computing":
                self.event_to_request.append(req)
        return
    
    def notify(self,event):
        if isinstance( event, TickEvent ):
            for req in self.pull_request():
                self.treat_request(req)

        if isinstance(event,MapRequest):
            """
            if event.args["type"]=="new_mapview_dimention":
                self.qq_to_router.put(event)
            """
            if event.args["type"]=="new_destination":
                self.qq_to_router.put(event)
            if event.args["type"]=="new_start_point":
                self.qq_to_router.put(event)

        if isinstance(event,GpsEvent):
            if event.args["type"]=="new_location":
                self.qq_to_router.put(event)

        if isinstance(event,StopEvent):
            self.qq_to_router.put(event)


        return True
    
    def get_requested_event(self):
        out=[]
        while len(self.event_to_request):
            out.append(self.event_to_request.pop(0))
        return out


class TtsController(Controller):
    def __init__(self):
        Controller.__init__(self)        
        import sayhooTts
        self.event_to_request=[]
        self.qq_to_tts=Queue.Queue()
        self.qq_from_tts=Queue.Queue()
        self.tts=sayhooTts.sayhooTts(self.qq_to_tts,self.qq_from_tts)



    def pull_request(self):
        out=[]
        while self.qq_from_router.qsize():
            try:
                ev=self.qq_from_router.get(False,30)
                out.append(ev)
            except:
                raise
            
        return out

    def treat_request(self,req):
        return

    def notify(self,event):
        if isinstance(event,StopEvent):
            self.qq_to_tts.put(event)

        if isinstance(event,StartEvent):
            self.qq_to_tts.put(event)

        return True

    def get_requested_event(self):
        out=[]
        while len(self.event_to_request):
            out.append(self.event_to_request.pop(0))
        return out

    
        
class ConsoleController(Controller):
    def __init__(self):
        Controller.__init__(self)        
        import sayhooConsole
        self.qq_to_console=Queue.Queue()
        self.qq_from_console=Queue.Queue()
        self.console=sayhooConsole.Console(self.qq_to_console,self.qq_from_console)
        self.event_to_request=[]
        return
    
    def pull_request(self):
        out=[]
        while self.qq_from_console.qsize():
            try:
                ev=self.qq_from_console.get(False,30)
                out.append(ev)
            except:
                raise
        return out    

    def treat_request(self,req):
        print "ConsoleController treat_request not implemented yet"
        if isinstance(req,GpsEvent):
            if req.args["type"]=="new_location":
                self.event_to_request.append(req)
        return

    def notify(self,event):
        if isinstance( event, TickEvent ):
            for req in self.pull_request():
                self.treat_request(req)

        if isinstance(event,StopEvent):
            self.qq_to_console.put(event)


    def get_requested_event(self):
        out=[]
        while len(self.event_to_request):
            out.append(self.event_to_request.pop(0))
        return out

class GpsController(Controller):
    """
    http://pymaemo.garage.maemo.org/documentation/python_gps_examples/index.html
    """
    def __init__(self):
        Controller.__init__(self)
        self.gps_context=False
        self.gps_device=False
        self.gps_available=False
        self.time_counter=0
        self.event_to_request=[]
        return

    def init_gps(self):
        print "Starting gps"
        if is_maemo():
            self.gps_context=gpsbt.start()
        else:
            self.gps_context=None

        if self.gps_context == None:
            print _('Problem while connecting to gps device!')
            return False
        time.sleep(2)
        if is_maemo():
            self.gps_device = gpsbt.gps()
        return True


    def fetch_gps_data(self):
        #print "fetching gps data"
        if self.gps_context==None:
            #print "no gps_context"
            return

        try:
            fix=self.gps_device.get_fix()
            cur_mode=self.gps_device.fix.mode
            cur_time=self.gps_device.fix.time
            cur_lat=self.gps_device.fix.latitude
            cur_lon=self.gps_device.fix.longitude
            cur_speed=self.gps_device.fix.speed
            cur_track=self.gps_device.fix.track
        except:
            print "Problem getting gps fix"
            return

        arg={"type":"new_location","lat":cur_lat,"lon":cur_lon,"track":cur_track}
        event=GpsEvent(args=arg)
	print "gps info=",arg
	if cur_lat!=0.0:
	    print "looks like a genuine location"
            self.event_to_request.append(event)
        
    def notify(self,event):
        
        if isinstance(event,TickEvent):
	    #print "time_counter=",self.time_counter
            if self.time_counter>5:
                self.fetch_gps_data()
                self.time_counter=0
            self.time_counter+=1

            
        if isinstance(event,StartEvent):
            if self.init_gps():
                self.gps_available=True


        if isinstance(event,StopEvent):
            if self.gps_context and is_maemo():
                gpsbt.stop(self.gps_context)
            print "Stopping gps"
        
    def get_requested_event(self):
        out=[]
        while len(self.event_to_request):
            out.append(self.event_to_request.pop(0))
        return out
            
class ManagerThread:

    def __init__(self):
        import gtk
        import time

        
        gtk.gdk.threads_init()
        self.running=True
        self.event_manager = EventManager()

        self.gui_controller=GuiController()
        self.event_manager.register_listener(self.gui_controller)

        self.map_controller=MapController()
        self.event_manager.register_listener(self.map_controller)

        self.console_controller=ConsoleController()
        self.event_manager.register_listener(self.console_controller)

        self.gps_controller=GpsController()
        self.event_manager.register_listener(self.gps_controller)

        self.tts_controller=TtsController()
        self.event_manager.register_listener(self.tts_controller)
        
        self.tick_thread=threading.Thread(target=self.tick)
        self.tick_thread.setDaemon(True)
        self.tick_thread.start()

        self.event_manager.post(StartEvent())
        try:
            gtk.main()
        except:
            print "Ke passa" 
            self.running=False
            self.event_manager.post(StopEvent())
            raise
        
        self.running=False

    def tick(self):
        while self.running:
            e=TickEvent()
            self.event_manager.post(e)
            self.event_manager.fetch()
            time.sleep(1)

        ev=StopEvent()
        self.event_manager.post(ev)



if __name__ == "__main__":
    mthread=ManagerThread()

        
