 (ns cmr.search.test.services.legacy-parameters
   (:require [clojure.test :refer :all]
             [cmr.search.services.legacy-parameters :as lp]
-            [clojure.test.check.generators :as gen]
+            [clojure.test.check.generators :refer [such-that] :as gen]
             [clojure.test.check.properties :refer [for-all]]
             [ring.util.codec :as rc]
             [cmr.search.services.messages.attribute-messages :as a-msg]

  (import clojure.lang.ExceptionInfo))


(defn- legacy-psa-map->legacy-psa-query
  "Convert a map of psa fields into a legacy psa url query string"
  [psa-map]
  (let [{:keys [name type value minValue maxValue]} psa-map
        [name type value minValue maxValue] (map #(when % (rc/url-encode %))
                                                 [name type value minValue maxValue])
        query (format "attribute%%5B%%5D%%5Bname%%5D=%s&attribute%%5B%%5D%%5Btype%%5D=%s" name type)]
    (if value
      (str query "&attribute%5B%5D%5Bvalue%5D=" value)
      (str query
           (when minValue (str "&attribute%5B%5D%5BminValue%5D=" minValue))
           (when maxValue (str "&attribute%5B%5D%5BmaxValue%5D=" maxValue))))))


(defn- legacy-psa-map->cmr-psa-query
  "Converts a map of psa fields into a map with a single attribute as a comma-separated string"
  [psa-map]
  (let [{:keys [name type value minValue maxValue]} psa-map
        [name type value minValue maxValue] (map #(when % (s/replace % "," "\\,"))
                                                 [name type value minValue maxValue])
        query (format "%s,%s" type name)
        query (if value
                (str query "," value)
                (str query "," minValue "," maxValue))]
    query))


;; NOTE - these don't generate valid psa fields, but that doesn't matter because we are only
;; testing that the legacy->cmr functionality reformats the query parameters correctly.



;; Tests that all generated legacy-psa attribute stings can be converted to cmr format.
(defspec legacy-psa->cmr-test 1
  (for-all [legacy-psa (such-that not-empty (gen/vector legacy-psa-maps))]
    (let [legacy-query (legacy-psa-maps->legacy-psa-query legacy-psa)
          cmr-psa-query (legacy-psa-maps->cmr-psa-query legacy-psa)
          result (lp/process-legacy-psa {:page-size 10} legacy-query)]
      (= {:page-size 10 :attribute cmr-psa-query} result))))

(lp/process-legacy-psa {} (legacy-psa-maps->legacy-psa-query [{:name "A,B" :type "string" :value nil :minValue "B,C" :maxValue "D,E"}]))

(legacy-psa-maps->cmr-psa-query [{:name "A,B" :type "string" :value nil :minValue "B,C" :maxValue "D,E"}])

;; Test for specific cases
(deftest handle-legacy-psa
  (are [name type value min-value max-value]
       (let [m {:name name :type type :value value :minValue min-value :maxValue max-value}]
         (= {:attribute (legacy-psa-maps->cmr-psa-query [m])}
            (lp/process-legacy-psa {} (legacy-psa-maps->legacy-psa-query [m]))))
       "A,B" "string" nil "B,C" "D,E"
       "A&B" "string" nil "P[C" "Q?r"
       "M[]N" "string" "A&? ;" nil nil))
