   (memoize -get-queue-url))
 
 (defrecord SQSQueueBroker
- [
+  ;; A record containig fields related to accessing SNS/SQS exchanges and queues.
+  [
    ;; Connection to AWS SNS
    sns-client
 

  [sns-client exchange-name]
  (let [exchange-name (normalize-queue-name exchange-name)
        topics (into [] (.getTopics (.listTopics sns-client)))]
   (some (fn [topic] (let [topic-arn (.getTopicArn topic)
                           topic-name (arn->name topic-arn)]
                      (when (= exchange-name topic-name)
                       topic)))
         topics)))

(def get-topic
 "Memoized function that returns the Topic with the given display name."

          topic (get-topic sns-client exchange-name)
          topic-arn (.getTopicArn topic)
          subs (into [] (.getSubscriptions (.listSubscriptionsByTopic sns-client topic-arn)))]
      (map (fn [sub]
               (->> sub
                    .getEndpoint
                    arn->name
                    (normalized-queue-name->original-queue-name this)))
           subs)))

  (publish-to-exchange
    [this exchange-name msg]
    (let [msg (json/generate-string msg)
          exchange-name (normalize-queue-name exchange-name)
          topic (get-topic sns-client exchange-name)
          topic-arn (.getTopicArn topic)]
      (.publish sns-client topic-arn msg)))

  (subscribe
    [this queue-name handler]
    (let [queue-name (normalize-queue-name queue-name)]
      (create-async-handler this queue-name handler)))

  (reset
    [this]
    (let [sqs-client (:sqs-client this)]
      (doseq [queue (:queues this)
              :let [queue-name (normalize-queue-name queue)
                    dlq-name (dead-letter-queue queue-name)
                    queue-url (.getQueueUrl (.getQueueUrl sqs-client queue-name))
                    dlq-url (.getQueueUrl (.getQueueUrl sqs-client dlq-name))
                    q-purge-req (PurgeQueueRequest. queue-url)
                    dlq-purge-req (PurgeQueueRequest. dlq-url)]]
        (.purgeQueue sqs-client q-purge-req)
        (.purgeQueue sqs-client dlq-purge-req))))

  (health
    [this]
    ;; try to get a list of queues and topics (exchanges) to test the connection to SNS/SQS
    (try
      (.listQueues sqs-client)
      (.listTopics sns-client)
      {:ok? true}
      (catch Throwable e
        {:ok? false :msg (.getMessage e)}))))

(record-pretty-printer/enable-record-pretty-printing SQSQueueBroker)

(defn create-queue-broker
  "Creates a broker that uses SNS/SQS"
  [{:keys [queues exchanges queues-to-exchanges]}]
  (->SQSQueueBroker nil nil queues nil exchanges queues-to-exchanges))

;; Tests to make sure SNS/SQS is working
(comment
  ;; create a broker
  (def broker (lifecycle/start (create-queue-broker {}) nil))
  ;; list the topics for the cmr-ingest_exchange exchange/topic
  (get-topic (:sns-client broker) "cmr_ingest_exchange")
  ;; list the queues for the cmr_ingest_exchange
  (queue/get-queues-bound-to-exchange broker "cmr_ingest_exchange")
  ;; create a test queue
  (create-queue (:sqs-client broker) "cmr-test.queue")
  ;; subscribe to test queue with a simple handler that prints received messages
  (queue/subscribe broker "cmr-test.queue" (fn [msg] (println "Got Message: " msg)))
  ;; publish a message to the queue to verify our subscribe worked
  (queue/publish-to-queue broker "cmr-test.queue" "{\"body\": \"ABC\"}"))
