 (ns mount.core
   (:require [clojure.tools.macro :as macro]
-            [clojure.tools.logging :refer [info warn debug error]]))
+            [clojure.tools.logging :refer [info]]))
 
 ;; (defonce ^:private session-id (System/currentTimeMillis))
 (defonce ^:private mount-state 42)

      `(defonce ~(with-meta state (merge (meta state) s-meta))
         (NotStartedState. ~(str state))))))

(defn- up [var {:keys [ns name start started? resume suspended?]}]
  (when-not started?
    (let [s (try (if suspended?
                   (do (info ">> resuming.. " name)
                       (resume))
                   (do (info ">> starting.. " name)
                       (start)))
                 (catch Throwable t
                   (throw (RuntimeException. (str "could not start [" name "] due to") t))))]
      (intern ns (symbol name) s)
      (alter-meta! var assoc :started? true :suspended? false))))

(defn- down [var {:keys [ns name stop started? suspended?]}]
  (when (or started? suspended?)
    (info "<< stopping.. " name)
    (when stop 
      (try
        (stop)
        (catch Throwable t
          (throw (RuntimeException. (str "could not stop [" name "] due to") t)))))
    (intern ns (symbol name) (NotStartedState. name)) ;; (!) if a state does not have :stop when _should_ this might leak
    (alter-meta! var assoc :started? false :suspended? false)))

(defn- sigstop [var {:keys [ns name started? suspend resume]}]
  (when (and started? resume)        ;; can't have suspend without resume, but the reverse is possible
    (info ">> suspending.. " name)
    (when suspend                    ;; don't suspend if there is only resume function (just mark it :suspended?)
      (let [s (try (suspend)
                   (catch Throwable t
                     (throw (RuntimeException. (str "could not suspend [" name "] due to") t))))]
        (intern ns (symbol name) s)))
    (alter-meta! var assoc :started? false :suspended? true)))

(defn- sigcont [var {:keys [ns name start started? resume suspended?]}]
  (when (instance? NotStartedState var)
    (throw (RuntimeException. (str "could not resume [" name "] since it is stoppped (i.e. not suspended)"))))
  (when suspended?
    (info ">> resuming.. " name)
    (let [s (try (resume)
                 (catch Throwable t
                   (throw (RuntimeException. (str "could not resume [" name "] due to") t))))]
      (intern ns (symbol name) s)

         (sort-by :order))))

(defn- bring [states fun order]
  (let [done (atom #{})]
    (->> states
         (sort-by (comp :order meta) order)
         (map #(fun % (meta %) done))
         doall)
    @done))

(defn merge-lifecycles 
  "merges with overriding _certain_ non existing keys. 
