const fs = require('fs');
const ObjectId = require('mongodb').ObjectId;

const datafire = require('../index');

const flow = module.exports = new datafire.Flow('convertToV2', "Converts a v1 flow to v2");
const mongo = datafire.Integration.new('mongodb').as('dfread2');

flow.setDefaults({
  flow_id: '',
  out_file: './flow-v2.js',
});

const convertName = (key) => {
  key = key.substring(key.indexOf(':') + 1);
  key = key.replace(/^www./, '');
  key = key.replace(/\.(com|net|org|gov)$/, '');
  return key.replace(/\W/g, '_');
}

const convertScript = (script, links) => {
  script = script.replace(/^[\s\S]*function\s+request\s*\(\s*(.*)\s*\)\s*\{/, '($1) => {');
  script = script.replace(/data\[(\d+)\]/g, (match, dataIdx) => {
    let link = links[+dataIdx];
    return 'data.' + link.name + dataIdx;
  });
  script = script.replace(/constants\./g, 'flow.params.');
  return script.split('\n').join('\n  ');
}

const getV2Code = (v1, links) => {
  links.forEach(l => l.name = convertName(l.key));
  let code = `

const datafire = require('datafire');
const flow = module.exports = new datafire.Flow("${v1.title}", "${v1.description || ''}");
`
  let integrated = [];
  links.forEach(link => {
    if (integrated.indexOf(link.name) !== -1) return;
    integrated.push(link.name);
    code += `const ${link.name} = datafire.Integration.new('${link.name}')\n`
  });

  let extraCode = v1.links
      .map(l => l.script)
      .map(script => {
        return script.match(/^([\s\S]*)function\s+request/);
      })
      .filter(m => m && m[1])
      .map(m => m[1])
      .filter(m => m)
      .join('\n');
  extraCode = extraCode.split('\n').filter(line => !line.startsWith('//')).join('\n');
  code += extraCode.trim();

  v1.links.forEach((l, idx) => {
    let link = links[idx];
    code += `
flow.step('${link.name}${idx}', {
  do: ${link.name}.${l.operation.method}("${l.operation.path}"),
  params: ${convertScript(l.script, links)}
})
`
  })
  return code.trim();
}

flow
  .step('flow_v1', {
    do: mongo.findOne('chains'),
    params: data => {
      return {
        query: {_id: ObjectId(flow.params.flow_id)}
      }
    }
  })
  .step('links', {
    do: mongo.findOne('connections'),
    params: data => {
      return data.flow_v1.links.map(l => ({
        query: {_id: ObjectId(l.connection)},
      }))
    }
  })
  .step('write', {
    do: data => {
      fs.writeFileSync(flow.params.out_file, getV2Code(data.flow_v1, data.links))
    }
  })

@@ -15,24 +15,86 @@
 uire('fs');%0A
+const path = require('path');%0Aconst async = require('async');%0A
 const Object
@@ -127,16 +127,16 @@
 jectId;%0A
-
 %0Aconst d
@@ -365,20 +365,19 @@
 ,%0A  out_
-file
+dir
 : './flo
@@ -387,24 +387,571 @@
 2.js',%0A%7D);%0A%0A
+const unescapeString = function(str) %7B%0A  return str.replace(/%5C%5Cu0024/g, '$').replace(/%5C%5Cu002E/g, '.');%0A%7D%0A%0Aconst unescapeKeys = function(obj) %7B%0A  if (!obj %7C%7C typeof obj !== 'object') return obj;%0A  var out = %7B%7D, o, k;%0A  for (var key in obj) %7B%0A    o = obj%5Bkey%5D;%0A    k = unescapeString(key);%0A    if (Array.isArray(o)) %7B%0A      out%5Bk%5D = o.map(function(inner) %7Breturn unescapeKeys(inner, unescapeString)%7D);%0A    %7D else if (typeof o === 'object') %7B%0A      out%5Bk%5D = unescapeKeys(o, unescapeString);%0A    %7D else %7B%0A      out%5Bk%5D = o;%0A    %7D%0A  %7D%0A  return out;%0A%7D;%0A%0A
 const conver
@@ -2925,16 +2925,113 @@
     %7D))%0A
+    %7D,%0A    finish: data =%3E %7B%0A      data.links.forEach(l =%3E l.swagger = unescapeKeys(l.swagger));%0A
     %7D%0A  
@@ -3093,16 +3093,26 @@
 ileSync(
+path.join(
 flow.par
@@ -3123,12 +3123,23 @@
 out_
-file
+dir, 'flow.js')
 , ge
@@ -3173,16 +3173,321 @@
 links))%0A
+      let integrationsDir = path.join(flow.params.out_dir, 'integrations');%0A      try %7B%0A        fs.mkdirSync(integrationsDir);%0A      %7D catch (e) %7B%7D%0A      data.links.forEach(l =%3E %7B%0A        fs.writeFileSync(path.join(integrationsDir, l.name + '.openapi.json'), JSON.stringify(l.swagger, null, 2));%0A      %7D)%0A
     %7D%0A  

add integrations to convert-to-v2