"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = loginToBitSrc;

function _http() {
  const data = _interopRequireDefault(require("http"));

  _http = function () {
    return data;
  };

  return data;
}

function _uuid() {
  const data = _interopRequireDefault(require("uuid"));

  _uuid = function () {
    return data;
  };

  return data;
}

function _opn() {
  const data = _interopRequireDefault(require("opn"));

  _opn = function () {
    return data;
  };

  return data;
}

function _os() {
  const data = _interopRequireDefault(require("os"));

  _os = function () {
    return data;
  };

  return data;
}

function _chalk() {
  const data = _interopRequireDefault(require("chalk"));

  _chalk = function () {
    return data;
  };

  return data;
}

function _url() {
  const data = _interopRequireDefault(require("url"));

  _url = function () {
    return data;
  };

  return data;
}

function _globalConfig() {
  const data = require("../../api/consumer/lib/global-config");

  _globalConfig = function () {
    return data;
  };

  return data;
}

function _constants() {
  const data = require("../../constants");

  _constants = function () {
    return data;
  };

  return data;
}

function _exceptions() {
  const data = require("../exceptions");

  _exceptions = function () {
    return data;
  };

  return data;
}

function _logger() {
  const data = _interopRequireDefault(require("../../logger/logger"));

  _logger = function () {
    return data;
  };

  return data;
}

function _generalError() {
  const data = _interopRequireDefault(require("../../error/general-error"));

  _generalError = function () {
    return data;
  };

  return data;
}

function _driver() {
  const data = require("../../driver");

  _driver = function () {
    return data;
  };

  return data;
}

const ERROR_RESPONSE = 500;
const DEFAULT_PORT = 8085;
const REDIRECT = 302;

function loginToBitSrc(port, suppressBrowserLaunch, npmrcPath, skipRegistryConfig, machineName) {
  let actualNpmrcPath = npmrcPath;
  return new Promise((resolve, reject) => {
    const clientGeneratedId = (0, _uuid().default)();

    const driver = _driver().Driver.load(_constants().DEFAULT_LANGUAGE);

    if ((0, _globalConfig().getSync)(_constants().CFG_USER_TOKEN_KEY)) {
      // $FlowFixMe
      return resolve({
        isAlreadyLoggedIn: true
      });
    }

    const server = _http().default.createServer((request, response) => {
      const closeConnection = statusCode => {
        if (statusCode) response.statusCode = statusCode;
        response.end();
        server.close();
      };

      if (request.method !== 'GET') {
        _logger().default.errorAndAddBreadCrumb('login.loginToBitSrc', 'received non get request, closing connection');

        closeConnection();
        reject(new (_exceptions().LoginFailed)());
      }

      try {
        const {
          clientId,
          redirectUri,
          username,
          token
        } = _url().default.parse(request.url, true).query || {};
        let writeToNpmrcError = false;

        if (clientGeneratedId !== clientId) {
          _logger().default.errorAndAddBreadCrumb('login.loginToBitSrc', 'clientId mismatch, expecting: {clientGeneratedId} got {clientId}', {
            clientGeneratedId,
            clientId
          });

          closeConnection(ERROR_RESPONSE);
          reject(new (_exceptions().LoginFailed)());
        }

        (0, _globalConfig().setSync)(_constants().CFG_USER_TOKEN_KEY, token);
        const configuredRegistry = (0, _globalConfig().getSync)(_constants().CFG_REGISTRY_URL_KEY);

        if (!skipRegistryConfig) {
          try {
            if (!configuredRegistry) {
              // some packages might have links in package-lock.json to the previous registry
              // this makes sure to have also the auth-token of the previous registry.
              // (the @bit:registry part points only to the current registry).
              actualNpmrcPath = driver.npmLogin(token, npmrcPath, _constants().PREVIOUSLY_DEFAULT_REGISTRY_URL);
            }

            actualNpmrcPath = driver.npmLogin(token, npmrcPath, configuredRegistry || _constants().DEFAULT_REGISTRY_URL);
          } catch (e) {
            actualNpmrcPath = e.path;
            writeToNpmrcError = true;
          }
        }

        response.writeHead(REDIRECT, {
          Location: redirectUri
        });
        closeConnection();
        resolve({
          username,
          npmrcPath: actualNpmrcPath,
          writeToNpmrcError
        });
      } catch (err) {
        _logger().default.err(`err on login: ${err}`);

        closeConnection(ERROR_RESPONSE);
        reject(new (_exceptions().LoginFailed)());
      }
    });

    _logger().default.debugAndAddBreadCrumb('login.loginToBitSrc', `initializing login server on port: ${port || DEFAULT_PORT}`);

    server.listen(port || DEFAULT_PORT, err => {
      if (err) {
        _logger().default.errorAndAddBreadCrumb('login.loginToBitSrc', 'something bad happened', {}, err);

        reject(new (_exceptions().LoginFailed)());
      }

      const encoded = encodeURI(`${(0, _globalConfig().getSync)(_constants().CFG_HUB_LOGIN_KEY) || _constants().DEFAULT_HUB_LOGIN}?port=${port || DEFAULT_PORT}&clientId=${clientGeneratedId}&responseType=token&deviceName=${machineName || _os().default.hostname()}&os=${process.platform}`);

      if (!suppressBrowserLaunch) {
        console.log(_chalk().default.yellow(`Your browser has been opened to visit:\n${encoded}`)); // eslint-disable-line no-console

        (0, _opn().default)(encoded);
      } else {
        console.log(_chalk().default.yellow(`Go to the following link in your browser::\n${encoded}`)); // eslint-disable-line no-console
      }
    });
    server.on('error', e => {
      if (e.code === 'EADDRINUSE') {
        reject(new (_generalError().default)(`port: ${e.port} already in use, please run bit login --port <port>`));
      }

      reject(e);
    });
    return {};
  });
}