import type { $Application } from 'express';

import type Controller from './controllers/Controller'

const getFunctionArgumentNames = (func): Array<string> => {
  // First match everything inside the function argument parens.
  const args = func.toString().match(/function\s.*?\(([^)]*)\)/)[1];

  // Split the arguments string into an array comma delimited.
  return args.split(',').map(argument => {
    // Ensure no inline comments are parsed and trim the whitespace.
    return argument.replace(/\/\*.*\*\//, '').trim();
  }).filter(argument => !!argument);
};

export default (app: $Application, controllers: Array<Controller>): void => {
  controllers.map(controller => {
    Object.getOwnPropertyNames(
      Object.getPrototypeOf(controller),
    ).map(functionName => {
      const mappedFunction = controller[functionName];
      const {httpVerb, route} = mappedFunction;
      if (!httpVerb) {
        return;
      }

      const argumentNames = getFunctionArgumentNames(mappedFunction);
      app[httpVerb](route, (request, response) => {
        const values = argumentNames
          .map(argument => request.params[argument])
          .filter(value => typeof value !== undefined);
        console.log(values);
        const result = mappedFunction.apply(
          controller,
          [
            ...values,
            request.body,
          ]
        );

        response.status(result.status).json(result.data);
      });
    });
  });
};

@@ -1,20 +1,30 @@
+// @flow%0A%0A
 import type %7B $Appli
@@ -29,16 +29,37 @@
 lication
+, $Request, $Response
  %7D from 
@@ -69,17 +69,16 @@
 press';%0A
-%0A
 import t
@@ -123,16 +123,17 @@
 troller'
+;
 %0A%0Aconst 
@@ -164,16 +164,26 @@
  = (func
+: Function
 ): Array
@@ -419,32 +419,33 @@
 it(',').map(
+(
 argument
  =%3E %7B%0A    //
@@ -432,21 +432,36 @@
 argument
+: string): string
  =%3E
- %7B
 %0A    // 
@@ -526,23 +526,16 @@
 ce.%0A    
-return 
 argument
@@ -567,21 +567,20 @@
 ).trim()
-;
+,
 %0A  
-%7D
 ).filter
@@ -580,24 +580,25 @@
 .filter(
+(
 argument
  =%3E !!ar
@@ -585,24 +585,42 @@
 er((argument
+: string): boolean
  =%3E !!argume
@@ -698,14 +698,8 @@
 er%3E)
-: void
  =%3E 
@@ -714,19 +714,24 @@
 rollers.
-map
+forEach(
 (control
@@ -733,16 +733,29 @@
 ntroller
+: Controller)
  =%3E %7B%0A  
@@ -831,19 +831,24 @@
 ,%0A    ).
-map
+forEach(
 (functio
@@ -852,16 +852,25 @@
 tionName
+: string)
  =%3E %7B%0A  
@@ -935,16 +935,17 @@
  const %7B
+ 
 httpVerb
@@ -951,16 +951,17 @@
 b, route
+ 
 %7D = mapp
@@ -1090,16 +1090,17 @@
 ction);%0A
+%0A
       ap
@@ -1126,19 +1126,40 @@
 (request
-, r
+: $Request, response: $R
 esponse)
@@ -1216,24 +1216,25 @@
    .map(
+(
 argument
  =%3E requ
@@ -1225,16 +1225,33 @@
 argument
+: string): string
  =%3E requ
@@ -1294,23 +1294,36 @@
 ter(
+(
 value
- =%3E typeof
+: ?Object): boolean =%3E
  val
@@ -1345,36 +1345,8 @@
 d);%0A
-        console.log(values);
 %0A   
@@ -1384,13 +1384,12 @@
 ion.
-apply
+call
 (%0A  
@@ -1412,22 +1412,8 @@
 er,%0A
-          %5B%0A  
     
@@ -1429,18 +1429,16 @@
 values,%0A
-  
         
@@ -1457,20 +1457,8 @@
 dy,%0A
-          %5D%0A
     

fix routeConfig, add some annotations