   https.get url, (response) ->
     if response.statusCode == 200
       stream = response.pipe fs.createWriteStream(dest)
+      stream.on 'error', (error) ->
+        callback error
       stream.on 'close', () ->
-        callback null, url, dest # TODO: Gonna drop an error here.
-    else
-      callback true, url, dest # TODO: Error is true?
+        callback null
+    else
+      callback true # TODO: Error is true?
 
 
 # Downloads an image file from a URL and opens it.
 #
 # @param [String] url the URL to download the image from
-# @param [String] dest the destination file on disk
-# @param [Function] callback the function to call back on
-#
-requestImage = (url, dest, callback) ->
-  downloadToDisk url, dest, (error, url, dest) ->
-    jimp.read dest, callback
-
-
-downloadHits = (hits, callback, files) ->
+# @param [String] filename the destination file on disk
+# @param [Function] callback the function to call back on
+#
+# @example How to call this function
+#   requestImage url, filename, (error, img) ->
+#     console.log img
+#
+requestImage = (url, filename, callback) ->
+  downloadToDisk url, filename, (error) ->
+    jimp.read filename, callback
+
+
+# Caches the smallest resolution in a set of hits locally in a temporary folder.
+#
+# @param [Array] hits the hits to cache
+# @param [Function] callback the function to call back on
+# @param [Array] files used for head recursion
+#
+# @example How to call this function
+#   cacheHitsLocally hits, (error, files) ->
+#     console.log files
+#
+cacheHitsLocally = (hits, callback, files) ->
   if !files then files = [] # Initialize array for head recursion.
   if hits.length == 0
     callback null, files # Base case.
   else
-    item = hits.pop()
-    dest = "./picksel_temp/#{item.id_hash}.jpg"
-    files.push {filename:dest, hash:item.id_hash}
-    downloadToDisk item.previewURL, dest, (error, url, dest) ->
-      if !error
-        downloadHits hits, callback, files # Recursively process.
+    hit = hits.pop() # Take next hit.
+    filename = "#{AMBIG_DIR}/#{hit.id_hash}.temp"
+    file =
+      filename: filename
+      hash: hit.id_hash
+    files.push file # Push new file.
+    downloadToDisk hit.previewURL, filename, (error) ->
+      if error
+        callback error, null # Error during download.
       else
-        callback true, null
-
-
-matchImage = (base, files, callback, percs) ->
-  if !percs then percs = [] # Initialize array for head recursion.
+        cacheHitsLocally hits, callback, files # Recursively process.
+
+
+# Gets the perceptual distances for a set of image files from a base image.
+#
+# @param [Object] base the base image
+# @param [Array] files the files to compare to the base image
+# @param [Function] callback the function to call back on
+# @param [Array] distances used for head recursion
+#
+# @example How to call this function
+#   getDistances base, files, (error, distances) ->
+#     console.log distances
+#
+getDistances = (base, files, callback, distances) ->
+  if !distances then distances = [] # Initialize array for head recursion.
   if files.length == 0
-    callback null, percs # Base case.
+    callback null, distances # Base case.
   else
-    file = files.pop()
-    jimp.read file.filename, (error, img) ->
+    file = files.pop() # Take next file.
+    jimp.read file.filename, (error, img) -> # Load up next image.
       if error
         callback error, null
       else
-        percs.push {hash: file.hash, distance: jimp.distance(base, img)}
-        matchImage base, files, callback, percs
+        distance =
+          hash: file.hash
+          distance: jimp.distance base, img
+        distances.push distance # Push new distance.
+        getDistances base, files, callback, distances # Recurse.
+
+
+# Returns the closest match from an array of distances.
+#
+# @param [Array] matches the array of distances to examine
+# @param [Object] closest used for head recursion
+#
+getClosest = (matches, closest) ->
+  if matches.length == 0 then return closest # Base case.
+  next = matches.pop()
+  best = if closest && closest.distance <= next.distance then closest else next
+  getClosest matches, best
+
+
+# Reslolves an ambiguous set of image results encountered while attempting to
+# derive a hash ID from an ID.
+#
+# @param [Object] base the base image to compare
+# @param [Array] hits the ambiguous array of hits from the Pixabay API
+# @param [Function] callback the function to call back on
+#
+# @example How to call this function
+#   resolveAmbiguousResults base, hits, (error, hashId) ->
+#     console.log hashId
+#
+resolveAmbiguousResults = (base, hits, callback) ->
+  mkdir AMBIG_DIR, (error) -> # Create temporary folder.
+    if error
+      callback error, null # Couldn't create folder.
+    else
+      cacheHitsLocally hits, (error, files) ->
+        if error
+          log.error 'Couldn\'t download thumbnails for perceptual hashing.'
+          callback error, null # Failed, couldn't download files.
+        else
+          getDistances base, files, (error, distances) ->
+            rimraf AMBIG_DIR, fs, (error) -> # Delete temporary folder.
+              if error
+                log.warn "Couldn't clean up temporary folder at #{AMBIG_DIR}!"
+              else
+                rimraf AMBIG_BASE_PATH, fs, (error) -> # Delete temporary file.
+                  if error
+                    log.warn 'Couldn\'t clean up temporary file at' \
+                      + " #{AMBIG_BASE_PATH}!"
+                  else
+                    callback null, getClosest(distances).hash # Success!
 
 
 # Tries to derive the hash ID of the image with the given numeric ID.

#
# @param [String] apiKey the API key to use for the request
# @param [Number] id the ID of the image to get information for
# @param [Number] resolution the resolution code of the image to get
#
buildUrl = (apiKey, id, resolution) ->
  code = humanResolutionToCode resolution


# Checks whether or not a human-readable resolution name is valid.
#
# @param [String] resolution the human-readable resolution name to check
#
isValidResolution = (resolution) -> humanResolutionToCode(resolution) > -1


# Persists an object to a file as JSON.
