#!/usr/bin/python2.5
# -*- coding: iso-8859-15 -*-
###################################################
#
# HXM heart beat main
# Version 22.2.2010
# Jari Multisilta
#
##################################################

import sys
import gtk
import gobject
import hildon
import threading
import pango
import pdb
import time
from HXMConnection import *

import dbus
import gobject
import dbus.glib
import conic
import location
from dprint import *

_bclock = threading.Lock()


#
# Callback function for location device
#
def on_error(control, error, data):
    dprint("location error: %d... quitting" % error)

#
# Callback function for location device
#
def on_stop(control, data):
    dprint("location quitting")

# Callback function for GPS fix. Is called whenever GPS fix is changed.
# We update the location to global variables lat and lon.
def on_changed(device, data):

    if not device:
        return
    if device.fix:
        if device.fix[1] & location.GPS_DEVICE_LATLONG_SET:
            _bclock.acquire()
            try: data.lat = device.fix[4]
            finally: _bclock.release()
            _bclock.acquire()
            try: data.lon = device.fix[5]
            finally: _bclock.release()


class HXMUI(threading.Thread):
 # A thread lock, in case needed
 lock = threading.Lock()
 # A frequency of the loop call (in milliseconds)
 TIMEOUT = 200


 def on_window_delete(self, widget, data=None):
   if self.connection == True:
      self.belt.disconnect()
   gtk.main_quit()
   return False


 def loop(self):
   time.sleep(0.1)          
   self.label_title.set_text(self.msg)
# Get latest heading update from belt manager and display update if different from prev
   if self.connection == True:
      heading = self.belt.getCurrentHeading()
      if heading != self.lastBeltHeading:
        self.lastBeltHeading = heading
        self.msg = "Current HR"
        self.label.set_text('%d' %(heading))
        self.label_bat.set_text(self.belt.getCurrentBat())
   return True

#
# Method for Connect button clicked
#
 def button_clicked(self, button, user_data):
    self.control.start()
    if self.connection == False:
      self.belt = HXMConnection(self)
      self.belt.start()

#
# Method for disconnect button clicked
#
 def disconnect_button_clicked(self, button, user_data):
    if self.connection == False:
        self.msg = "Disconnected"
    elif self.belt.isConnected == True:
      self.belt.disconnect()
      self.msg = "Disconnected"
      self.lastBeltHeading = 0
      self.connection = False
      self.label.set_text("000")
      self.label_bat.set_text("B:----")

#
# Method for creating Connect button
#
 def create_button(self):
    button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT,
                           hildon.BUTTON_ARRANGEMENT_VERTICAL)
    button.set_text("Connect", "")
    button.connect("clicked", self.button_clicked, "ok")
    return button


 def __init__(self):
   self.app = hildon.Program.get_instance()    
   gtk.set_application_name("HXM")
   
   window = hildon.StackableWindow()
   self.window = window
   self.connection = False

   # Initialize tracking variables
   self.lastBeltHeading = 0
   self.msg = "Not connected"

   # Create a label for heart beat
   self.label = gtk.Label("000")
   self.label.set_justify(gtk.JUSTIFY_CENTER)
   self.label.modify_font(pango.FontDescription("sans 144"))
   
   # Label for messages 
   self.label_title = gtk.Label("")
   self.label_title.set_justify(gtk.JUSTIFY_CENTER)
   self.label_title.modify_font(pango.FontDescription("sans 40"))
 
   # Label for battery indicator
   self.label_bat = gtk.Label("B:---- ")
   self.label_bat.set_justify(gtk.JUSTIFY_LEFT)
   self.label_bat.modify_font(pango.FontDescription("sans 40"))

   # Create connect button
   self.button = self.create_button()

   # Create disconnect HXM button 
   self.button_disconnect = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT,
                           hildon.BUTTON_ARRANGEMENT_VERTICAL)
   self.button_disconnect.set_text("Disconnect", "")
   self.button_disconnect.connect("clicked", self.disconnect_button_clicked, None)

   # Layout
   vbox = gtk.VBox(False, 20)

   hhbox = gtk.HBox(False, 20)
   hhbox.pack_start(self.label_title, True, True, 0)
   hhbox.pack_start(self.label_bat, False, True, 0)
   vbox.pack_start(hhbox, True, True, 0)

   vbox.pack_start(self.label, True, True, 0)

   hbox = gtk.HBox(False, 20)
   hbox.pack_start(self.button, True, True, 0)
   hbox.pack_start(self.button_disconnect, True, True, 0)
   vbox.pack_end(hbox, False, True, 0)

   window.add(vbox)
   window.connect("delete_event", self.on_window_delete)

   # For location
   self.control = location.GPSDControl.get_default()
   self.device = location.GPSDevice()
   self.control.set_properties(preferred_method=location.METHOD_USER_SELECTED,
                       preferred_interval=location.INTERVAL_DEFAULT)
   self.device.connect("changed", on_changed, self)
   self.control.connect("error-verbose", on_error, self)
   self.control.connect("gpsd-stopped", on_stop, self)
   self.lat = 0.0
   self.lon = 0.0
   threading.Thread.__init__(self)
 

 def myloop(self):
       gobject.timeout_add(self.TIMEOUT, self.loop)
 

 def show(self):
   self.window.show_all()
 
#############################################################################
# MAIN
#############################################################################

# This is ESSENTIAL if you are using multi-threading in a GTK app.  There are
# cleaner ways to do the same using gobject, but I'm using the brute force for
# the sake of sanity
gtk.gdk.threads_init()

if __name__ == "__main__": 
 
 ui = HXMUI()
 ui.start()
 ui.show()
 ui.myloop()

# The threads_enter() and threads_leave() calls are ESSENTIAL for apps with
# multi-threaded intereaction
 gtk.gdk.threads_enter()
 gtk.main()
 gtk.gdk.threads_leave()
