"use strict";

var _keys = require("babel-runtime/core-js/object/keys");

var _keys2 = _interopRequireDefault(_keys);

var _promise = require("babel-runtime/core-js/promise");

var _promise2 = _interopRequireDefault(_promise);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var simctl = require("node-simctl");
var execSync = require("child_process").execSync;
var path = require("path");
var ora = require("ora");
var download = require("download");
var fs = require("fs");

var ios = function ios(prefix, deviceType, appUrl, schema, params) {
  var result = {};
  return findDevice(prefix, deviceType, result).then(function (udid) {
    return openIosSimulator(udid).then(function () {
      try {
        openApp(udid, schema, params);
        return result;
      } catch (e) {
        return loadApp(appUrl).then(function (path) {
          return simctl.installApp(udid, path).then(function () {
            openApp(udid, schema, params);
            return result;
          });
        });
      }
    });
  });
};

function openApp(udid, schema, params) {
  execSync("xcrun simctl openurl " + udid + " " + schema + "://" + (params ? "?" + params : ""), {
    stdio: "ignore"
  });
}

function openIosSimulator(udid) {
  return new _promise2.default(function (resolve, reject) {
    try {
      execSync("xcrun instruments -w " + udid, {
        stdio: "ignore"
      });
    } catch (e) {}
    var timestamp = new Date().getTime();

    function checker() {
      var booted = false;
      simctl.getDevices().then(function (deviceMap) {
        (0, _keys2.default)(deviceMap).forEach(function (sdk) {
          deviceMap[sdk].forEach(function (device) {
            if (device.udid === udid && device.state === "Booted") {
              booted = true;
            }
          });
        });
        if (booted) {
          resolve();
        } else if (new Date().getTime() - timestamp < 30000) {
          setTimeout(checker, 500);
        } else {
          reject(new Error({
            type: "simulator",
            message: "simulator start timeout!"
          }));
        }
      });
    }
    checker();
  });
}

function findDevice(prefix, deviceType, result) {
  var find = void 0;
  var deviceName = prefix + " " + deviceType;
  return new _promise2.default(function (resolve, reject) {
    simctl.getDevices().then(function (deviceMap) {
      (0, _keys2.default)(deviceMap).forEach(function (sdk) {
        deviceMap[sdk].forEach(function (device) {
          if (device.name === deviceName) {
            find = device;
          }
        });
      });
      if (!find) {
        result.firstCreate = true;
        createDevice(prefix, deviceType).then(function (udid) {
          return resolve(udid);
        });
      } else {
        resolve(find.udid);
      }
    });
  });
}

function createDevice(prefix, deviceType) {
  return simctl.createDevice(prefix + " " + deviceType, deviceType, getRuntime());
}

function getRuntime() {
  var runtimes = JSON.parse(execSync("xcrun simctl list runtimes --json").toString().trim());
  return runtimes["runtimes"].filter(function (r) {
    return r.name.indexOf("iOS") >= 0;
  })[0].identifier;
}

function loadApp(appUrl) {
  return new _promise2.default(function (resolve, reject) {
    if (/^(https?|ftp)/.test(appUrl)) {
      var schema = appUrl.split("|");
      var url = schema[0];
      var location = schema[1] || path.basename(appUrl, path.extname(appUrl)) + ".app";
      var targetPath = path.join(process.env["HOME"], ".simrun/", path.join("weexplayground", location));
      if (fs.existsSync(targetPath)) {
        return resolve(targetPath);
      }
      var spinner = ora("Download weexplayground ...").start();
      download(url, path.join(process.env["HOME"], ".simrun/weexplayground/"), {
        extract: /\.(zip|tgz)$/.test(url)
      }).then(function () {
        spinner.stop();
        resolve(targetPath);
      }, function (e) {
        return reject(e);
      });
    } else {
      resolve(appUrl);
    }
  });
}

module.exports = {
  ios: ios
};