;;; ha-focus.el --- Emacs lisp code to focus my thoughts. -*- lexical-binding: t; -*-
;;
;; Copyright © 2021,2024 Howard X. Abrams
;;
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams>
;; Maintainer: Howard X. Abrams <howard.abrams@gmail.com>
;; Created: May 28, 2021
;;
;; This file is not part of GNU Emacs.
;;
;;; Commentary:
;;
;; Find details of this code on my website at:
;;     https://www.howardism.org/Technical/Emacs/focused-work.html
;;
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
;;            ~/website/Technical/Emacs/focused-work.org
;;       And tangle the file to recreate this one.
;;
;;; Code:

(defvar ha-focus-timer nil "A timer reference for the ha-focus functions")

(defun ha-focus-countdown-timer (minutes fun)
  (let ((the-future (* minutes 60)))
    (setq ha-focus-timer (run-at-time the-future nil fun))))

(defun ha-focus-begin ()
  "Start a concerted, focused effort, ala Pomodoro Technique.
We first clock into the current org-mode header (or last one),
start some music to indicate we are working, and set a timer.

Call `ha-focus-break' when finished."
  (interactive)
  (ha-focus-countdown-timer 25 'ha-focus-break)
  (ha-focus--command "tell application \"VLC\" to play")
  (if (eq major-mode 'org-mode)
      (org-clock-in)
    (org-clock-in-last))
  (message "🍅 Started clocked %s"
           (substring-no-properties
            (org-clock-get-clock-string))))

(defun ha-focus-break ()
  "Stop the focused time by stopping the music.
This also starts another break timer, that calls
`ha-focus-break-over' when finished."
  (interactive)
  (run-with-idle-timer 30 nil 'ha-focus-capture)
  (ha-focus--command "tell application \"VLC\" to pause")
  (ha-focus-countdown-timer 5 'ha-focus-break-over)
  (message "🍅 Time to take a break."))

(defun ha-focus-capture ()
  "Spin up a capture window."
  (ignore-errors
    (org-capture nil "cc")
    (sit-for 1)
    (org-clock-out)))

(defun ha-focus-break-over ()
  "Message me to know that the break time is over. Notice that
this doesn't start anything automatically, as I may have
wandered off."
  (ha-focus--command "set v to output volume of (get volume settings)
set volume output volume 1
say \"Break time over. Back on your head.\"
set volume output volume v")
  (message "🍅 Type <f12> to restart the timer."))

(defun ha-focus-interrupt ()
  "Interrupt the current focused timer, if set."
  (interactive)
  (when (timerp ha-focus-timer)
    (cancel-timer ha-focus-timer)
    (ignore-errors
      (org-clock-out))))

(require 'async)

(defun ha-focus--command (osascript)
  "Runs OSASCRIPT by passing to the `osascript' command asynchronously."
  (async-start-process "focus-os" "osascript"
                       'ha-focus--command-callback "-e" osascript))

(defun ha-focus--command-callback (proc)
  "Asynchronously called when the `osascript' process finishes."
  ;; ...
  )

(provide 'ha-focus)
;;; ha-focus.el ends here
