 (def pixel-per-lon-degree (float (/ tile-size 360.0)))
 (def pixel-per-lon-radian (float (/ tile-size (* 2 (java.lang.Math/PI)))))
 
-(defn radians-to-degrees [rad]
+(defn- radians-to-degrees [rad]
   (float (/ rad (float (/ (java.lang.Math/PI) 180)))))
 
-(defn tile-lat-lon
+(defn- tile-lat-lon
   "Get the Latitude & Longitude of the upper left corner of a given tile"
   [x y zoom]
   (let [num-tiles (bit-shift-left 1 zoom)

        lon (float (/ (- corner-x pixel-origin) pixel-per-lon-degree))
        lat-radians (/ (- corner-y pixel-origin) (* pixel-per-lon-radian -1))
        lat (radians-to-degrees (- (* 2 (java.lang.Math/atan (java.lang.Math/exp lat-radians)))
                                   (/ 2 (java.lang.Math/PI))))]
    {:lat lat
     :lon lon}))


(defn query-with-inside-filter
  "Add an 'Inside' filter to the given query to restrict results to a bounding box"
  [details lat-field-id lon-field-id x y zoom]
  (let [{top-lt-lat :lat top-lt-lon :lon} (tile-lat-lon x y zoom)

        (assoc details :filter (conj ["AND"] (:filter details) inside-filter))))))


(defn- extract-points
  "Takes in a dataset query result object and pulls out the Latitude/Longitude pairs into nested `java.util.ArrayLists`.
   This is specific to the way we plan to feed data into `com.metabase.corvus.api.tiles.GoogleMapPinsOverlay`."
  [{{:keys [rows cols]} :data}]
  (if-not (> (count rows) 0)
    ;; if we have no rows then return an empty list of points
    (java.util.ArrayList. [])
    ;; otherwise we go over the data, pull out the lat/lon columns, and convert them to ArrayLists
    (let [find-col-idx (fn [special-type]
                         (->> (map-indexed (fn [idx itm] (when (= special-type (:special_type itm)) idx)) cols)
                              (filter identity)
                              (first)))
          lat-col-idx (find-col-idx "latitude")
          lon-col-idx (find-col-idx "longitude")]
      (->> (map (fn [row] (java.util.ArrayList. [(nth row lat-col-idx) (nth row lon-col-idx)])) rows)
           (java.util.ArrayList.)))))


;; This endpoints provides an image with the appropriate pins rendered given a json query
;; We evaluate the query and find the set of lat/lon pairs which are relevant and then render the appropriate ones
;; It's expected that to render a full map view several calls will be made to this endpoint in parallel
