'use strict';

const path = require('path');
const fs = require('fs');
const os = require('os');
const get = require('simple-get');
const pump = require('pump');
const tfs = require('tar-fs');
const zlib = require('zlib');
const pkg = require('./package.json');
const support = require('./support');

function onerror(err) {
  throw err;
}

/**
 * Download and Install prebuild
 * @param runtime
 * @param abi
 * @param platform
 * @param arch
 * @param cb Callback
 */
function install(runtime, abi, platform, arch, cb) {
  const essential = runtime + '-v' + abi + '-' + platform + '-' + arch;
  const pkgVersion = pkg.version;
  const currentPlatform = pkg.name + '-v' + pkgVersion + '-' + essential;
  
  console.log('Downloading prebuild for platform:', currentPlatform);
  let downloadUrl = 'https://github.com/WilixLead/iohook/releases/download/v' + pkgVersion + '/' + currentPlatform + '.tar.gz';
  
  let reqOpts = { url: downloadUrl };
  let tempFile = path.join(os.tmpdir(), 'prebuild.tar.gz');
  let req = get(reqOpts, function (err, res) {
    if (err) {
      return onerror(err);
    }
    if (res.statusCode !== 200) {
      if (res.statusCode === 400) {
        console.error('Prebuild for current platform (' + currentPlatform + ') not found!');
        console.error('Try to compile for your platform:');
        console.error('# cd node_modules/iohook;');
        console.error('# npm run compile');
        console.error('');
        return onerror('Prebuild for current platform (' + currentPlatform + ') not found!');
      }
      return onerror('Bad response from prebuild server. Code: ' + res.statusCode);
    }
    pump(res, fs.createWriteStream(tempFile), function (err) {
      if (err) {
        throw err;
      }
      let options = {
        readable: true,
        writable: true,
        hardlinkAsFilesFallback: true
      };
      let binaryName;
      let updateName = function (entry) {
        if (/\.node$/i.test(entry.name)) binaryName = entry.name
      };
      let targetFile = path.join(__dirname, 'builds', essential);
      let extract = tfs.extract(targetFile, options)
        .on('entry', updateName);
      pump(fs.createReadStream(tempFile), zlib.createGunzip(), extract, function (err) {
        if (err) {
          return onerror(err);
        }
        cb()
      })
    })
  });

  req.setTimeout(30 * 1000, function () {
    req.abort()
  })
}

/**
 * Return options for iohook from package.json
 * @return {Object}
 */
function optionsFromPackage() {
  const packageFile = path.join(process.cwd(), 'package.json');
  const content = fs.readFileSync(packageFile, 'utf-8');
  const packageJson = JSON.parse(content);

  return packageJson.iohook || {
    targets: [],
    platforms: [],
    arches: []
  };
}

const options = optionsFromPackage();
if (process.env.npm_config_targets) {
  options.targets = options.targets.concat(process.env.npm_config_targets.split(','));
}
if (process.env.npm_config_platforms) {
  options.platforms = options.platforms.concat(process.env.npm_config_platforms.split(','));
}
if (process.env.npm_config_arches) {
  options.arches = options.arches.concat(process.env.npm_config_arches.split(','));
}

// Choice prebuilds for install 
if (process.argv.indexOf('--all') > -1 || options.targets) {
  let chain = Promise.resolve();
  let targets;
  if (process.env.npm_config_targets === 'all') { // If need install all targets
    targets = support.targets
  } else {
    targets = options.targets.map(targetStr => targetStr.split('-'));
  }
  let platforms = options.platforms ? options.platforms : ['win32', 'darwin', 'linux'];
  let arches = options.arches ? options.arches : ['x64', 'ia32'];
  
  targets.forEach(function (parts) {
    let runtime = parts[0];
    let version = parts[1];
    platforms.forEach(function (platform) {
      arches.forEach(function (arch) {
        if (platform === 'darwin' && arch === 'ia32') {
          return;
        }
        chain = chain.then(function () {
          return new Promise(function (resolve) {
            let abi = support.abis[runtime][version];
            console.log(runtime, abi, platform, arch);
            install(runtime, abi, platform, arch, resolve)
          })
        })
      })
    })
  })
} else {
  const runtime = process.versions['electron'] ? 'electron' : 'node';
  const abi = process.versions.modules;
  const platform = process.platform;
  const arch = process.arch;
  install(runtime, abi, platform, arch, function () {})
}

@@ -2504,76 +2504,241 @@
 age(
-) %7B%0A  const packageFile = path.join(process.cwd(), 'package.json');%0A
+attempts) %7B%0A  attempts = attempts %7C%7C 1;%0A  if (attempts %3E 5) %7B%0A    throw new Error('Can%5C't resolve main package.json file');%0A  %7D%0A  let mainPath = attempts === 1 ? './' : Array(attempts).join(%22../%22);%0A  console.log(mainPath);%0A  try %7B%0A  
   co
@@ -2773,17 +2773,41 @@
 c(pa
-ckageFile
+th.join(mainPath, 'package.json')
 , 'u
@@ -2814,16 +2814,18 @@
 tf-8');%0A
+  
   const 
@@ -2856,24 +2856,56 @@
 (content);%0A%0A
+    console.log(packageJson);%0A  
   return pac
@@ -2925,24 +2925,28 @@
 ok %7C%7C %7B%0A    
+   
+ 
 targets: %5B%5D,
@@ -2942,24 +2942,28 @@
 argets: %5B%5D,%0A
+    
     platform
@@ -2969,24 +2969,28 @@
 ms: %5B%5D,%0A    
+ 
+   
 arches: %5B%5D%0A 
@@ -2990,18 +2990,87 @@
 s: %5B%5D%0A  
+    %7D;%0A  %7D catch (e) %7B%0A    return optionsFromPackage(attempts + 1);%0A  
 %7D
-;
 %0A%7D%0A%0Acons

Test push