;;; d-meal-timer.el --- A meal timer count-down system that improves over appt.el

;; Copyright (C) 2006-2011 Davin Pearson

;; Author/Maintainer: m4_davin_pearson
;; Keywords: Meal time
;; Version: 1.0

;;; Commentary:

;; This file is not part of GNU Emacs.

;; Have you ever sat programming on your computer only to realise that
;; the cooking on your stove top has been burnt for want of lack of
;; care of your cooking.  For those of you who are out there, this
;; system is for you.  You simply execute M-x meal-timer and the
;; minibuffer prompts you for a time to elapse before a sound sample
;; is played.  While the timer is counting down, the number of hours,
;; minutes and seconds remaining is continuously updated on the mode
;; line.  This is a superior replacement to the built-in appt.el
;; system.

;;; m4_limitation_of_warranty

;;; m4_install_instructions(d-meal-timer)

;;; Known Bugs:

;; none!

;;; Code:

(require 'd-time)

(setq meal-timer-on nil)
(setq meal-timer--stopped-time nil)

;;(defvar meal-timer--file "c:/music/already-burnt-8GB/B52s--Love-Shack.wma")
;;(defvar meal-timer--file "c:/music/mc-hammer--keep.wma")
;;(defvar meal-timer--file "c:/music/midi-150MB/Midi-Popular/B52s/Love-Shack.mid")
;;(defvar meal-timer--file "~/c++-projects/2007/R4/music/Africa.mid")

;; (seconds-to-readable-string 123 nil t)
;; (seconds-to-readable-string 12.3 nil t)
(defun meal-timer (minutes)
  (interactive "nEnter Meal Timer (minutes): ")
  (let ((seconds nil))
    (if meal-timer-on
        (cancel-function-timers 'meal-timer-function))
    ;;(cancel-timer meal-timer))
    (if (< minutes 0)
        (error "You cannot enter a negative time"))
    ;;(message "minutes=%s" minutes)
    (setq meal-timer--on t)
    (setq meal-timer--beep-time (current-time))
    (setq seconds (* 60.0 minutes))
    (setq meal-timer--duration (seconds-to-readable-string seconds nil t))
    ;;(setq seconds (meal-timer--minutes-to-seconds minutes 'meal-timer--beep-time))
    (setq meal-timer--total-time-in-seconds seconds)
    ;;(setq foo (current-time))
    ;;(meal-timer--minutes-to-seconds 1 'foo)
    (setq meal-timer (run-with-timer seconds nil 'meal-timer-function))
    ))

;;(defun meal-timer--minutes-to-seconds (minutes var)
;;  (let (hi lo seconds)
;;    (setq var (eval var))
;;    (setq hi (car var))
;;    (setq lo (cadr var))
;;    (setq seconds (* 60.0 minutes))
;;    (setq lo (+ lo seconds))
;;    (while (>= lo 65536)
;;      (setq lo (- lo 65535))
;;      (setq hi (+ hi 1)))
;;    (assert (< lo 65536))
;;    (assert (< hi 65536))
;;    (setcar var hi)
;;    (setcar (cdr var) lo)
;;    seconds
;;    ))

(defun meal-timer-stop ()
  (interactive)
  (if (not meal-timer--on)
      (d-beeps "Cannot stop meal timer as meal timer is off")
    (setq meal-timer--on nil)
    (setq meal-timer--secs (- meal-timer--total-time-in-seconds
                              (abs (seconds-of-time-difference meal-timer--beep-time (current-time)))))
    (cancel-function-timers 'meal-timer-function)
    (setq meal-timer--stopped-time (current-time))
    ))

(defun meal-timer-start ()
  (interactive)
  (if meal-timer--on
      (d-beeps "Cannot start meal timer as meal timer is on")
    (setq meal-timer--on t)
    (setq meal-timer--total-time-in-seconds meal-timer--secs)
    (setq meal-timer--beep-time (current-time))
    (setq meal-timer--duration (seconds-to-readable-string meal-timer--secs nil t))
    (setq meal-timer (run-with-timer meal-timer--secs nil 'meal-timer-function))))

(defun meal-timer-function ()
  ;;(d-nbeeps 5 "Time is up!")
  ;; NOTE: Better replacement for sit-for
  (setq meal-timer--on nil)
  (setq meal-timer--stopped-time nil)
  (if (fboundp 'd-fonts) (d-fonts))
  (sit-for 1)
  (let (f)
    (setq f "completed-meal-timer.wav")
    (if (file-exists-p f)
        (play-sound (list 'sound :file f :volume .99)))
    (setq f "c:/sound-samples/emacs/completed-meal-timer.wav")
    (if (file-exists-p f)
        (play-sound (list 'sound :file f :volume .99)))
    (setq f "/media/www/C1TB/sound-samples/emacs/completed-meal-timer.wav")
    (if (file-exists-p f)
        (play-sound (list 'sound :file f :volume 1.0)))
    )
  (d-beeps "Meal timer expired at %s elasped=%s" (d-time--get-stamp) meal-timer--duration)
  (if (fboundp 'd-fonts) (d-fonts))
  (redraw-display)
  )

;;(setq minor-mode-alist (cons '(meal-timer--on " MEAL-TIMER") minor-mode-alist))
;;(setq minor-mode-alist (cons '(meal-timer--on (:eval (meal-timer-get-string))) minor-mode-alist))
(setq minor-mode-alist (cons '(:eval (meal-timer-get-string)) minor-mode-alist))

;; (setq s "123 ")
;; (substring s 0 -1)
(setq meal-timer--on nil)

(defun meal-timer-get-string ()
  (if meal-timer--on
      (let* ((count (- meal-timer--total-time-in-seconds
                       (abs (seconds-of-time-difference meal-timer--beep-time (current-time)))))
             (count (floor count))
             (str (seconds-to-readable-string count nil t)))
         (format " Timer=(%s/%s)" str meal-timer--duration))
    (if meal-timer--stopped-time
        (let* ((count (- meal-timer--total-time-in-seconds
                         (abs (seconds-of-time-difference meal-timer--beep-time meal-timer--stopped-time))))
               (count (floor count))
               (str (seconds-to-readable-string count nil t)))
          (format " Timer=(%s)" str)))))

(run-with-timer 1 1 'force-mode-line-update)

;;(run-with-idle-timer 10 nil 'd-foo)

(provide 'd-meal-timer)
;;; d-meal-timer.el ends here
