 (defn plugins-config []
   (get-config ::plugins-config [:plugins]))
 
-(defn all-namespaces []
+(defn all-namespaces
+  "find and return all namespaces found on the (system)classpath"
+  []
   (concat
    (ns/find-namespaces (cp/system-classpath))
    (ns/find-namespaces (cp/classpath))))
 
-(defn find-namespaces [pattern]
+(defn find-namespaces
+  "find-n-filter namespaces based on a provided pattern"
+  [pattern]
   (->> (all-namespaces)
        (filter #(re-matches pattern (str %)))
        (distinct)))
+
+; mycompany.plugins.commands.*
+(def all-command-plugins-regex #"^.*plugins\.commands.*")
 
 (def yetibot-command-namespaces
   [;; support for e.g.:

   ;; yetibot.core.commands.*
   ;; yetibot-pluginname.commands.*
   #"^yetibot(\S*)\.(core\.)?commands.*"
   ;; mycompany.plugins.commands.*
   #"^.*plugins\.commands.*"
   ])

(comment
  (find-namespaces
    (first yetibot-command-namespaces)))

(def yetibot-observer-namespaces
  [#"^yetibot\.(core\.)?observers.*" #"^.*plugins\.observers.*"])

(def yetibot-all-namespaces
  (merge
    (map last [yetibot-command-namespaces
               yetibot-observer-namespaces])
    ; with a negative lookahead assertion
    #"^yetibot\.(.(?!(core)))*"))

(defn load-ns [arg]
  (debug "Loading" arg)
  (try (require arg)
       arg
       (catch Exception e
         (warn "WARNING: problem requiring" arg "hook:" (.getMessage e))
         (st/print-stack-trace (st/root-cause e) 15))))

(defn find-and-load-namespaces
  "Find namespaces matching ns-patterns: a seq of regex patterns. Load the matching
   namespaces and return the seq of matched namespaces."
  [ns-patterns]
  (let [nss (flatten (map find-namespaces ns-patterns))]
    (info "☐ Loading" (count nss) "namespaces matching" ns-patterns)
    (dorun (map load-ns nss))
    (info "☑ Loaded" (count nss) "namespaces matching" ns-patterns)
    nss))

(defn load-commands []
  (find-and-load-namespaces yetibot-command-namespaces))

(defn load-observers []
  (find-and-load-namespaces yetibot-observer-namespaces))

(ns yetibot.core.loader
  (:require
   [taoensso.timbre :refer [debug info warn]]
   [yetibot.core.config :refer [get-config]]
   [clojure.spec.alpha :as s]
   [yetibot.core.spec :as yspec]
