-;; Copyright (c) 2014-2015 Andrey Antukh <niwi@niwi.nz>
-;; Copyright (c) 2014-2015 Alejandro Gómez <alejandro@dialelo.com>
+;; Copyright (c) 2014-2016 Andrey Antukh <niwi@niwi.nz>
+;; Copyright (c) 2014-2016 Alejandro Gómez <alejandro@dialelo.com>
 ;; All rights reserved.
 ;;
 ;; Redistribution and use in source and binary forms, with or without

  (:require [cats.protocols :as p]))

(def ^:dynamic *context* nil)
(def ^:const +level-default+ 10)
(def ^:const +level-transformer+ 100)

(defn throw-illegal-argument
  {:no-doc true :internal true}

     `(with-context ~ctx
        ~@body)))

;; TODO: improve error messages

(defn infer
  "Given an optional value infer its context. If context is already set, it
  is returned as is without any inference operation."
  {:no-doc true}
  ([]
   (if (nil? *context*)
     (throw-illegal-argument "No context is set.")
     *context*))
  ([v]
   (cond
     (not (nil? *context*))
     *context*

     (satisfies? p/Contextual v)
     (p/-get-context v)

     (satisfies? p/Context v)
     v

     :else
     (throw-illegal-argument
      (str "No context is set and it can not be automatically "
           "resolved from provided value")))))

(defn get-current
  "Deprecated alias to `infer`."
  {:deprecated true}
  [& args]
  (apply infer args))


