/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

var services = {
      youtube: require( "./youtube" ),
      soundcloud: require( "./soundcloud" ),
      flickr: require( "./flickr" ),
      giphy: require( "./giphy" )
    },
    qs = require( "querystring" ),
    async = require( "async" ),
    LIMIT;

function validate( options, validateCallback ) {
  var query = options.query.q;

  if ( !query ) {
    return validateCallback( "[webmaker-mediasync]: Request must contain a query" );
  }

  options.query.q = qs.escape( query );
  options.limit = LIMIT;

  validateCallback( null, options );
}

module.exports = function( limit ) {
  LIMIT = limit || 30;

  module.exports = {
    all: function( options, callback ) {
      validate( options, function( err, options ) {
        if ( err ) {
          return callback( err );
        }

        function callService( type, asyncCallback ) {
          services[ type ]( options, asyncCallback );
        }

        async.map( Object.keys( services ), callService, function( err, results ) {
          if ( err ) {
            return callback( err );
          }

          callback( null, {
            results: results
          });
        });
      });
    },
    youtube: function( options, callback ) {
      validate( options, function( err, options ) {
        if ( err ) {
          return callback( err );
        }

        services.youtube( options, callback );
      });
    },
    soundcloud: function( options, callback ) {
      validate( options, function( err, options ) {
        if ( err ) {
          return callback( err );
        }

        services.soundcloud( options, callback );
      });
    },
    flickr: function( options, callback ) {
      validate( options, function( err, options ) {
        if ( err ) {
          return callback( err );
        }

        services.flickr( options, callback );
      });
    },
    giphy: function( options, callback ) {
      validate( options, function( err, options ) {
        if ( err ) {
          return callback( err );
        }

        services.giphy( options, callback );
      });
    }
  };
};
@@ -1005,54 +1005,175 @@
     
-function callService( type, asyncCallback
+var servicesArray = %5B%5D;%0A%0A        for ( var key in services ) %7B%0A          servicesArray.push((function( serviceKey, options ) %7B%0A            return function( cb
  ) %7B%0A
+    
     
@@ -1192,12 +1192,18 @@
 es%5B 
-type
+serviceKey
  %5D( 
@@ -1215,21 +1215,10 @@
 ns, 
-asyncCallback
+cb
  );%0A
@@ -1217,34 +1217,38 @@
 , cb );%0A        
-%7D%0A
+    %7D;
 %0A        async.m
@@ -1244,55 +1244,79 @@
     
-async.map( Object.keys( services ), callService
+  %7D)( key, options ));%0A        %7D%0A%0A        async.parallel( servicesArray
 , fu

Make search functionality run parallel for each service.