import { getUrl } from '../workers/babel.worker';
import * as Rollbar from '../utils/rollbar';
import validateType from './validateType';
var resolves = new Map();
var rejects = new Map();
var cache = new Map();
export default function babelFile(file) {
  if (!validateType('javascript', file.type)) {
    return Promise.resolve(''); // トランスパイル対象ではない
  }

  if (file.text.length > 100000) {
    return Promise.resolve(file.text); // 長すぎるのでスキップ
  }

  var worker = getWorker();
  var exist = cache.get(file.id);
  if (exist) return exist; // すでにトランスパイルが始まっている

  var promise = new Promise(function (resolve, reject) {
    // 後からイベントハンドラでコールできるように関数を保持する
    resolves.set(file.id, resolve);
    rejects.set(file.id, reject);
  }); // 同じファイルが複数呼ばれた時のために promise をキャッシュする

  cache.set(file.id, promise); // トランスパイル開始

  worker.postMessage({
    id: file.id,
    code: file.text,
    options: {
      filename: file.name
    }
  });
  return promise;
}
var worker = null;
var workerUrl = null;

function getWorker() {
  if (worker) return worker; // Initialize babel worker process

  workerUrl = workerUrl || getUrl();
  worker = new Worker(workerUrl);

  worker.onmessage = function (event) {
    // Result of transpiling
    var _ref = event.data,
        id = _ref.id,
        code = _ref.code,
        error = _ref.error;

    if (error) {
      // トランスパイルを試みたが, Syntax Error が見つかった
      var reject = rejects.get(id);

      if (!reject) {
        // エラーを伝える関数が登録されていない
        console.error(error);
        throw new Error("rejects[".concat(id, "] is not registered"));
      }

      var babelError = new Error(error.message);
      babelError.name = 'SyntaxError';
      babelError.stack = error.stack;
      reject(babelError);
      Rollbar.error(babelError);
      return;
    }

    var resolve = resolves.get(id);

    if (!resolve) {
      // 結果を伝える関数が登録されていない
      throw new Error("resolves[".concat(id, "] is not registered"));
    }

    resolve(code); // 結果を返す

    resolves.delete(id);
    rejects.delete(id);
  };

  worker.onerror = function (event) {
    // Babel Error ではなく, 致命的なエラーが発生した
    worker && worker.terminate();
    resolves.clear();
    rejects.clear();
    cache.clear();
    worker = null;
    console.warn('Babel Worker was terminated.');
    throw event.error;
  };

  return worker;
}