"use strict";

const walk                        = require('acorn/dist/walk');
const extractCommonJSDependencies = require("./extract-commonJS-deps");

module.exports = (pAST, pDependencies) => {
    walk.simple(
        pAST,
        {
            "ExpressionStatement": pNode => {
                // module as a function (define(Array, function))
                // module with a name (define(string, Array, function))
                // 'root' require module (require(Array, function)
                if (pNode.expression.type === "CallExpression" &&
                     pNode.expression.callee.type === "Identifier" &&
                     (pNode.expression.callee.name === "define" ||
                       pNode.expression.callee.name === "require")){
                    pNode.expression.arguments
                        .filter(pArg => pArg.type === "ArrayExpression")
                        .forEach(arg =>
                            arg.elements.forEach(el => {
                                if (Boolean(el.value) && typeof el.value === "string") {
                                    el.value.split('!').forEach(pString =>
                                        pDependencies.push({
                                            moduleName: pString,
                                            moduleSystem: "amd"
                                        })
                                    );
                                }
                            })
                        );
                }
                // CommonJS-wrappers:
                //  (define(function(require, exports, module){
                //  define(["require", ...], function(require, ...){
                //      ... every 'require' call is a depencency
                // Won't work if someone decides to name the first parameter of
                // the function passed to the define something else from "require"
                if (pNode.expression.type === "CallExpression" &&
                     pNode.expression.callee.type === "Identifier" &&
                     pNode.expression.callee.name === "define") {
                    pNode.expression.arguments
                        .filter(pArg => pArg.type === "FunctionExpression")
                        .filter(pFunction => pFunction.params.some(pParam => pParam.name === "require"))
                        .forEach(pFunction => extractCommonJSDependencies(pFunction.body, pDependencies, "amd"));
                }
            }
        }
    );
};

@@ -149,356 +149,71 @@
 );%0A%0A
-module.exports = (pAST, pDependencies) =%3E %7B%0A    walk.simple(%0A        pAST,%0A        %7B%0A            %22ExpressionStatement%22: pNode =%3E %7B%0A                // module as a function (define(Array, function))%0A                // module with a name (define(string, Array, function))%0A                // 'root' require module (require(Array, function)%0A            
+function extractRegularAMDDependencies(pNode, pDependencies) %7B%0A
     
@@ -266,37 +266,24 @@
  &&%0A        
-             
 pNode.expres
@@ -315,37 +315,24 @@
 ntifier%22 &&%0A
-             
         (pNo
@@ -381,35 +381,24 @@
             
-           
 pNode.expres
@@ -429,30 +429,19 @@
 quire%22))
+ 
 %7B%0A
-            
         
@@ -463,36 +463,24 @@
 n.arguments%0A
-            
             
@@ -536,36 +536,24 @@
             
-            
 .forEach(arg
@@ -559,36 +559,8 @@
 g =%3E
-%0A                           
  arg
@@ -585,32 +585,16 @@
 el =%3E %7B%0A
-                
         
@@ -678,32 +678,16 @@
         
-                
 el.value
@@ -716,16 +716,37 @@
 tring =%3E
+ pDependencies.push(%7B
 %0A       
@@ -766,53 +766,73 @@
     
-                pDependencies.push(%7B%0A        
+moduleName: pString,%0A                        moduleSystem: %22amd%22%0A
     
@@ -839,33 +839,37 @@
                 
- 
+%7D));%0A
                m
@@ -871,172 +871,630 @@
     
-moduleName: pString,%0A                                            moduleSystem: %22amd%22%0A                                        %7D)%0A                            
+ %7D%0A            %7D));%0A    %7D%0A%7D%0A%0Afunction extractCommonJSWrappers(pNode, pDependencies) %7B%0A    if (pNode.expression.type === %22CallExpression%22 &&%0A        pNode.expression.callee.type === %22Identifier%22 &&%0A        pNode.expression.callee.name === %22define%22) %7B%0A        pNode.expression.arguments%0A            .filter(pArg =%3E pArg.type === %22FunctionExpression%22)%0A            .filter(pFunction =%3E pFunction.params.some(pParam =%3E pParam.name === %22require%22))%0A            .forEach(pFunction =%3E extractCommonJSDependencies(pFunction.body, pDependencies, %22amd%22));%0A    %7D%0A%7D%0A%0Amodule.exports = (pAST, pDependencies) =%3E %7B%0A    walk.simple(%0A
         
 );%0A 
@@ -1481,34 +1481,37 @@
 simple(%0A        
-);
+pAST,
 %0A               
@@ -1495,32 +1495,34 @@
   pAST,%0A        
+%7B%0A
                 
@@ -1509,33 +1509,66 @@
   %7B%0A            
- 
+%22ExpressionStatement%22: pNode =%3E %7B%0A
            %7D%0A   
@@ -1564,87 +1564,272 @@
     
-  %7D%0A
        
-                     %7D)%0A                        );%0A                %7D
+// module as a function (define(Array, function))%0A                // module with a name (define(string, Array, function))%0A                // 'root' require module (require(Array, function)%0A                extractRegularAMDDependencies(pNode, pDependencies);
 %0A   
@@ -2244,510 +2244,37 @@
     
-if (pNode.expression.type === %22CallExpression%22 &&%0A                     pNode.expression.callee.type === %22Identifier%22 &&%0A                     pNode.expression.callee.name === %22define%22) %7B%0A                    pNode.expression.arguments%0A                        .filter(pArg =%3E pArg.type === %22FunctionExpression%22)%0A                        .filter(pFunction =%3E pFunction.params.some(pParam =%3E pParam.name === %22require%22))%0A                        .forEach(pFunction =%3E extractCommonJSDependencies(pFunction.body
+extractCommonJSWrappers(pNode
 , pD
@@ -2288,36 +2288,10 @@
 cies
-, %22amd%22));%0A                %7D
+);
 %0A   

break the anonymous call in the core AMD extractor in two functions