         imageFiles.push existingImageFile
   imageFiles
 
+findImagesURLs = (metadata) ->
+  imageURLs = []
+  for key, value of metadata
+    httpsRegexPattern = new RegExp("^(http|https)://", "i")
+    fileRegexPattern = new RegExp("([^\/]+\.(?:jpg|jpeg|gif|png|svg|mp4|txt))$", "i")
+    if httpsRegexPattern.test(value) && fileRegexPattern.test(value)
+      imageURLs.push value
+  imageURLs
+
+locationCreator = (mimeType, url) ->
+  location = {}
+  location[mimeType] = url
+  location
+
+
+createSubject = (subjectData) ->
+  return if ( !subjectData || !subjectData instanceof Object )
+  subject = apiClient.type('subjects').create(subjectData)
+  await subject.save().then(defer _).catch(console.error.bind console)
+  log "Saved subject #{subject.id}"
+  subject
+
 argOpts =
   alias:
     u: 'username'

      --subject-set "345"         If omitted, a new subject set is created
      --skip 50                   Skip the first N lines (per manifest file)
      --limit 100                 Only create N subjects (per manifest file)

    Notes:
      Multiple manifests will end up in the same subject set.

    log "On row #{i + 1} of #{rows.length}"

    metadata = getMetadata row
    
    if args.skipMediaUpload

      subject = {}
      subject.metadata = metadata
      subject.locations = []
      subject.links = project: args.project

      # find a https urls for the row
      imageURLs = findImagesURLs metadata
      if imageURLs.length is 0
        log "!!! Cannot find a https url for row #{i + 1}"
        break
      
      for url, url in imageURLs
        await request url, defer error, response
        
        if error?
          log "!!! Error requesting URL for row #{i + 1}:", error
          break
        
        if response?
          if response.statusCode == 200
            mimeType = mime.lookup url
            subject.locations.push locationCreator(mimeType, url)              
            
            newSubject = apiClient.type('subjects').create(subject)
            await newSubject.save().then(defer _).catch(console.error.bind console)
            log "Saved subject #{newSubject.id}"
            
            if newSubject?
              newSubjectIDs.push newSubject.id
            else
              log "!!! Error: No subject created."
            
          else
            log "!!! Error: Unexpected response code:", response.statusCode
            break


    # create subject with media upload
    else
      imageFileNames = findImagesFiles path.dirname(file), metadata

      if imageFileNames.length is 0
        console.error "!!! Couldn't find an image for row #{i + 1}"

      else
        subject = apiClient.type('subjects').create
          # Locations are sent as a list of mime types.
          locations: (mime.lookup imageFileName for imageFileName in imageFileNames)
          metadata: metadata
          links:
            project: args.project

        await subject.save().then(defer _).catch(console.error.bind console)
        log "Saved subject #{subject.id}"

        # Locations array has been transformed into [{"mime type": "URL to upload"}]
        for location, ii in subject.locations
          for type, url of location
            headers = {'Content-Type': mime.lookup imageFileNames[ii]}
            body = fs.readFileSync imageFileNames[ii]

            await request.put {headers, url, body}, defer error, response

            if response?
              if 200 <= response.statusCode < 400
                log "Uploaded image #{imageFileNames[ii]}"
                newSubjectIDs.push subject.id
              else
                error = response.body

            if error?
              console.error '!!! Failed to put image', error
              console.error "!!! Deleting subject #{subject.id}"
              await subject.delete().then(defer _).catch(console.error.bind console)
              break

if newSubjectIDs.length is 0
  log 'No subjects to link'
