"use strict";

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

var _promise2 = _interopRequireDefault(_promise);

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

var path = require("path");
var chalk = require("chalk");
var boxen = require("boxen");

var detect = require("detect-port");
var launcher = require("./util/launcher");
var headless = require("./server/headless");
var config = require("./config");
var debugServer = require("./server");
var mlink = require("./link");
var Router = mlink.Router;

var _require = require("./util"),
    logger = _require.logger,
    hosts = _require.hosts,
    util = _require.util;

var builder = require("@weexbox/builder");

function resolveBundleUrl(bundlePath, ip, port) {
  return "http://" + ip + ":" + port + "/" + config.BUNDLE_DIRECTORY + "/" + bundlePath.replace(/\.(we|vue)$/, ".js");
}

function isUrl(str) {
  return (/^https?:\/\//.test(str)
  );
}

function resolveRealUrl(url) {
  return url.replace(/^(https?:\/\/)([^/:]+)(?=:\d+|\/)/, function (m, a, b) {
    if (!/\d+\.\d+\.\d+\.\d+/.test(a)) {
      return a + hosts.findRealHost(b);
    } else {
      return m;
    }
  });
}

function resolveConnectUrl(config) {
  var host = config.ip + ":" + config.port;
  util.setConnectUrl(config.connectUrl || "http://" + host + "/devtool_fake.html?_wx_devtool=ws://" + host + "/debugProxy/native/{channelId}");
}

exports.startServerAndLaunch = function (ip, port, manual, cb) {
  var _this = this;

  this.startServer(ip, port).then(function () {
    cb && cb();
    if (!manual) _this.launch(ip, port);
  });
};

exports.startServer = function (ip, port) {
  return new _promise2.default(function (resolve, reject) {
    var inUse = config.inUse;
    var message = chalk.green("Start debugger server!");
    if (inUse) {
      message += " " + chalk.red("(on port " + inUse.open + "," + (" because " + inUse.old + " is already in use)"));
    }
    message += "\n\n";
    message += "- " + chalk.bold("Websocket Address For Native: ") + " ws://" + ip + ":" + port + "/debugProxy/native\n";
    message += "- " + chalk.bold("Debug Server:                 ") + " http://" + ip + ":" + port + "\n";
    debugServer.start(port, function () {
      logger.log(boxen(message, {
        padding: 1,
        borderColor: "green",
        margin: 1
      }));
      resolve();
    });
  });
};

exports.launch = function (ip, port) {
  var debuggerURL = "http://" + (ip || "localhost") + ":" + port + "/";
  logger.info("Launching Dev Tools...");
  if (config.ENABLE_HEADLESS) {
    // Check whether the port is occupied
    detect(config.REMOTE_DEBUG_PORT).then(function (open) {
      if (+config.REMOTE_DEBUG_PORT !== open) {
        headless.closeHeadless();
        logger.info("Starting inspector on port " + open + ", because " + config.REMOTE_DEBUG_PORT + " is already in use");
      } else {
        logger.info("Starting inspector on port " + open);
      }
      config.REMOTE_DEBUG_PORT = open;
      headless.launchHeadless(config.ip + ":" + config.port, open);
    });
  }
  launcher.launchChrome(debuggerURL, config.REMOTE_DEBUG_PORT || 9222);
};

exports.resolveBundlesAndEntry = function (entry, bundles, ip, port) {
  var entryUrl = void 0;
  var bundleUrls = bundles.filter(function (bundle) {
    return !/\.js\.map/.test(bundle);
  }).map(function (b) {
    return resolveBundleUrl(b, ip, port);
  });
  if (isUrl(entry)) {
    entryUrl = resolveRealUrl(entry);
    entryUrl = entryUrl.replace(/127\.0\.0\.1/g, ip);
    bundleUrls.push(entryUrl);
  }
  return bundleUrls;
};

exports.reload = function () {
  Router.get("debugger").pushMessage("proxy.native", {
    method: "WxDebug.refresh"
  });
};

exports.start = function (target, config, cb) {
  var _this2 = this;

  resolveConnectUrl(config);
  if (isUrl(target)) {
    var bundleUrls = this.resolveBundlesAndEntry(target, [], config.ip, config.port);
    config.bundleUrls = bundleUrls;
    this.startServerAndLaunch(config.ip, config.port, config.manual, cb);
  } else if (target) {
    var filePath = path.resolve(target);
    var shouldReloadDebugger = false;
    builder.build(filePath, path.join(__dirname, "../frontend", config.BUNDLE_DIRECTORY), {
      watch: true,
      ext: config.ext,
      min: config.min,
      devtool: "source-map"
    }, function (err, output, json) {
      if (err) {
        logger.error(err);
      } else {
        logger.log("Build completed!\n");
        logger.log(output.toString());
        if (!shouldReloadDebugger) {
          shouldReloadDebugger = true;
          var bundles = json.assets.map(function (o) {
            return o.name.replace("\\", "/");
          });
          var _bundleUrls = _this2.resolveBundlesAndEntry(config.entry, bundles, config.ip, config.port);
          config.BUNDLE_URLS = _bundleUrls;
          _this2.startServerAndLaunch(config.ip, config.port, config.manual, cb);
        } else {
          exports.reload();
        }
      }
    });
  } else {
    this.startServerAndLaunch(config.ip, config.port, config.manual, cb);
  }
};