;; fill-queue による非同期フックの実験
;; 指定したファイルの最終更新日時が変わったらキューにそのファイル名をプッシュする

(ns watch-file-status
  (:use [clojure.contrib.seq :only (fill-queue)])
  (:import [java.io File]
           [java.util Date]
           [java.text SimpleDateFormat]))

(defn- last-modified [filename] (.lastModified (File. filename)))
(defn- thread-name [] (.getName (Thread/currentThread)))

(defn modified-status
  "ファイル名をキー、その最終更新日時を値にしたマップを返す"
  [filenames]
  (reduce into (map #(hash-map % (last-modified %)) filenames)))

(defn watching-loop [fill filenames]
  (let [updater (partial modified-status filenames) ; update function
        last    (atom (updater))]
    (println "watching-loop thread:" (thread-name))
    (loop [now (updater)]
      (let [mods (filter #(> (now %) (@last %)) filenames)]
        (if-not (empty? mods)
          (do (doseq [f mods]
                (fill f)) ; hook
              (reset! last now))))
      (Thread/sleep 1000) ; interval 1 sec
      (recur (updater)))))

(defn show-file-status [filename]
  (let [dateformat (SimpleDateFormat. "yyyy-MM-dd HH:mm:ss")]
    (println "modified:" filename)
    (println "datetime:" (.format dateformat (last-modified filename)))))

;; main
(let [args *command-line-args*]
  (println "watching..." args)
  (println "main thread:" (thread-name))
  (doseq [changed-file (fill-queue (fn [fill] (watching-loop fill args)))]
    (show-file-status changed-file)))