#!/usr/bin/env python

# Author: Asko Tontti <http://maemo.org/profile/view/tontti/>

# mTracker - time tracker with log for Maemo
# Copyright 2009 Asko Tontti
#
# 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 of the License.
#
# 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

# todo
# -write a new StartStopButton widget

import os
import string
import time
import calendar

import gtk
import gobject
import hildon
import sqlite3

path, proc = os.path.split(__file__)
homedir = os.path.expanduser('~')

class DB:
  def __init__(self, name):
    sqlite3.register_converter("unixtime", self.convert_unixtime)
    self.conn = sqlite3.connect(name + ".sqlite",
                                detect_types=sqlite3.PARSE_COLNAMES)
    self.create()

  def create(self):
    c = self.conn.cursor()
    c.execute('create table if not exists log (id integer primary key, start text, duration real, description text, deleted integer)')
    self.conn.commit()

  def convert_unixtime(self, s):
    return calendar.timegm(time.strptime(s, '%Y-%m-%dT%H:%M:%S'))

  def save(self, start, duration, description):
    c = self.conn.cursor()
    s = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime(start))
    c.execute('insert into log(start, duration, description) values (?,?,?)',
              (s, duration, description))
    self.conn.commit()

  def orderByDate(self, count=None):
    c = self.conn.cursor()
    select = 'select start as "start [unixtime]", duration, description from log order by start desc'
    if count is None:
      c.execute(select)
    else:
      c.execute(select + ' limit ?', (count,))
    return c

class mTrackerApp(hildon.Program):
  RED = "red"
  GREEN = "#008800"

  def __init__(self):
    hildon.Program.__init__(self)
    self.db = DB(os.path.join(homedir, "MyDocs", ".mtracker"))
    self.initMainWindow()

  def initMainWindow(self):
    self.window = hildon.Window()
    self.window.set_title("mTracker")
    self.window.connect("destroy", gtk.main_quit)
    self.add_window(self.window)

    self.time = gtk.Label("")
    self.status = gtk.Label("Idle")
    self.button = gtk.Button()
    self.button.connect("clicked", self.clicked)
    self.history = gtk.TextView()
    self.history.set_editable(False)

    self.vMain = gtk.VBox(False, 10)
    self.vMain.pack_start(self.time)
    self.vMain.pack_start(self.status)
    self.vMain.pack_start(self.button)
    self.vMain.pack_start(self.history)

    self.running = False
    self.startTime = time.time()
    self.updateStatus()
    self.updateHistory()
    self.buttonStart()

    self.window.add(self.vMain)

  def buttonStart(self):
    self.button.set_label("Start")
    self.buttonMode = "start"

  def buttonStop(self):
    self.button.set_label("Stop")
    self.buttonMode = "stop"

  def clicked(self, widget):
    if self.buttonMode == "start":
      self.onStart(widget)
    else:
      self.onStop(widget)

  def onStart(self, widget):
    self.running = True
    self.startTime = time.time()
    self.updateStatus()
    self.buttonStop()
    self.timer = gobject.timeout_add(5000, self.updateStatus)

  def onStop(self, widget):
    gobject.source_remove(self.timer)
    self.running = False
    self.updateStatus()
    self.buttonStart()
    self.db.save(self.startTime, time.time() - self.startTime, "-")
    self.updateHistory()

  def dhms(self, secs):
    m = int(secs / 60)
    h = int(m / 60)
    d = int(h / 24)
    hms = "%02d:%02d:%02d" % (h % 24, m % 60, secs % 60)
    return "%d days %s" % (d, hms) if d > 0 else hms

  def fmttime(self, utc):
    return time.strftime('%Y-%m-%d\t%H:%M:%S', time.localtime(utc))

  def updateStatus(self):
    if self.running:
      text = "Running"
      now = time.strftime("%H:%M")
      color = mTrackerApp.RED
    else:
      text = "Idle"
      now = ""
      color = mTrackerApp.GREEN
    self.time.set_text(now)
    z = time.time() - self.startTime
    self.status.set_markup('<span foreground="%s" weight="bold" size="larger">%s  %s</span>' % (color, text, self.dhms(z)))
    return self.running

  def updateHistory(self):
    l = []
    for row in self.db.orderByDate(5):
      l.append("%s\t%s\t%s" % (self.fmttime(row[0]), self.dhms(row[1]), row[2]))
    while len(l) < 5:
      l.append("")
    self.history.get_buffer().set_text("\n".join(l))

  def run(self):
    self.window.show_all()
    gtk.main()

app = mTrackerApp()
app.run()

# the end
