 (defn- get-verifier-for-algorithm
   "Get verifier function for algorithm name."
   [^Keyword alg]
-  (when (contains? gsign/*signers-map* alg)
-    (get-in gsign/*signers-map* [alg :verifier])))
+  (when (contains? *signers-map* alg)
+    (get-in *signers-map* [alg :verifier])))
 
 (defn- get-signer-for-algorithm
   "Get signer function for algorithm name."
   [^Keyword alg]
-  (when (contains? gsign/*signers-map* alg)
-    (get-in gsign/*signers-map* [alg :signer])))
+  (when (contains? *signers-map* alg)
+    (get-in *signers-map* [alg :signer])))
 
 (defn- safe-encode
   "Properly encode string into

  [data]
  (into {} (remove (comp nil? second) data)))

(defn- make-headers
  "Encode jws header"
  [alg extra-headers]
  (-> (or extra-headers {})
      (merge {:alg (.toUpperCase (name alg)) :typ "JWS"})
      (json/generate-string)
      (codecs/str->bytes)
      (codecs/bytes->safebase64)))

(defn- make-claims
  "Encode jws claims."
  [input exp nbf iat]
  (-> (normalize-nil-claims {:exp exp :nbf nbf :iat iat})

    (-> (signer candidate pkey)
        (codecs/bytes->safebase64))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Public Api
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defn encode
  "Sign arbitrary length string/byte array using
  json web token/signature."
  [claims pkey & [{:keys [alg exp nbf iat headers] :or {alg :hs256 headers {}}}]]
  {:pre [(map? claims)]}
  (let [header (encode-header alg headers)
        claims (encode-claims claims exp nbf iat)
        signature (calculate-signature pkey alg header claims)]
    (either/right (str/join "." [header claims signature]))))

(defn decode
  "Given a signed message, verify it and return
  the decoded claims.

  This function returns a monadic either instance,
  and if some error is happens in process of decoding
  and verification, it will be reported in an
  either/left instance."
  [input pkey & [{:keys [maxage] :as opts}]]
  {:pre [(string? input)]}
  (let [[header claims signature] (str/split input #"\." 3)
        candidate (str/join "." [header claims])
        header (parse-header header)
        claims (parse-claims claims)
        algorithm (parse-algorithm header)
        signature (codecs/safebase64->bytes signature)
        verifier (get-verifier-for-algorithm algorithm)
        result (verifier candidate signature pkey)]
    (if (false? result)
      (either/left "Invalid token.")
      (let [now (to-timestamp (jodat/now))]
        ;; (println 2222 (> now (:exp claims)))
        (cond
          (and (:exp claims) (> now (:exp claims)))
          (either/left (format "Token is older than :exp (%s)" (:exp claims)))

          (and (:nbf claims) (> now (:nbf claims)))
          (either/left (format "Token is older than :nbf (%s)" (:nbf claims)))

          (and (:iat claims) (number? maxage) (< (- now (:iat claims)) maxage))
          (either/left (format "Token is older than :iat (%s)" (:iat claims)))

          :else
          (either/right claims))))))

(defn sign
  "Not monadic version of encode."
  [& args]
  (either/from-either (apply encode args)))

(defn unsign
  "Not monadic version of decode."
  [& args]
  (let [result (apply decode args)]
    (when (either/right? result)
      result)))
