"use strict";

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

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

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

function semver() {
  const data = _interopRequireWildcard(require("semver"));

  semver = function () {
    return data;
  };

  return data;
}

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

  _chalk = function () {
    return data;
  };

  return data;
}

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

  _constants = function () {
    return data;
  };

  return data;
}

function _loader() {
  const data = _interopRequireDefault(require("../../cli/loader/loader"));

  _loader = function () {
    return data;
  };

  return data;
}

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

  _exceptions = function () {
    return data;
  };

  return data;
}

const createMajorMessage = (remoteVersion, currentVersion) => _chalk().default.red(`Fatal: There is a mismatch between the remote server version - "${remoteVersion}" and your bit version - "${currentVersion}", please update\n`);

const createMinorMessage = (remoteVersion, currentVersion) => _chalk().default.yellow(`Warning: There is a mismatch between the remote server version - "${remoteVersion}" and your bit version - "${currentVersion}", please update\n`);
/**
 * before version 14.x there was no way for the server to throw a custom error regarding the
 * old client version. what we can do is throwing a generic error, which the client will
 * catch as UnexpectedNetworkError. Since the client shows an error itself (see
 * checkVersionCompatibility()) the user will get both errors: checkVersionCompatibility()
 * and checkVersionCompatibilityOnTheServer().
 *
 * Since version 14.x a new Error has created OldClientVersion, when the client uses a version
 * equal or bigger than 14.x it's easier to show the entire error using that class.
 */


const throwErrorFromServerSinceVersion = 14;

function checkVersionCompatibility(remoteVersion) {
  // In case the client is newer than the server version don't check computability
  // (Should be change in the future, but right now we won't release a client which we don't support
  //  on the server)
  if (semver().gte(_constants().BIT_VERSION, remoteVersion)) {
    return;
  }

  const remoteMajor = semver().major(remoteVersion);
  const remoteMinor = semver().minor(remoteVersion);
  const remotePatch = semver().patch(remoteVersion);
  const localMajor = semver().major(_constants().BIT_VERSION);
  const localMinor = semver().minor(_constants().BIT_VERSION);
  const localPatch = semver().patch(_constants().BIT_VERSION);

  if (remoteMajor > localMajor) {
    if (localMajor < throwErrorFromServerSinceVersion) return;

    _loader().default.stop();

    console.log(createMajorMessage(remoteVersion, _constants().BIT_VERSION)); // eslint-disable-line

    _loader().default.start();

    return;
  }

  if (remoteMinor > localMinor) {
    _loader().default.stop();

    console.log(createMajorMessage(remoteVersion, _constants().BIT_VERSION)); // eslint-disable-line

    _loader().default.start();

    return;
  }

  if (remotePatch > localPatch) {
    _loader().default.stop();

    console.log(createMinorMessage(remoteVersion, _constants().BIT_VERSION)); // eslint-disable-line

    _loader().default.start();
  }
}
/**
 * throw error when the server has a major version bigger than the client.
 *
 * we're trying to be backward compatible whenever possible, however, to be forward compatible
 * is much more difficult.
 * It's safer to not let an old client interact with the server at all than enabling some commands
 * and blocking others per version.
 * Imagine when a migration script is written (e.g. when a model field is changed) and it updates
 * some hashes of the components from the old version. If a client doesn't update its version and
 * is using an old version, the flow will break sooner or later with hash-not-found exception
 */


function checkVersionCompatibilityOnTheServer(clientVersion) {
  const clientMajor = semver().major(clientVersion);
  const localMajor = semver().major(_constants().BIT_VERSION);
  const oldClientVersionMessageUntilV14 = `Please update your Bit client.\nFor additional information: https://${_constants().BASE_DOCS_DOMAIN}/docs/latest-version.html`;

  const oldClientVersionMessageAfterV14 = () => `Fatal: Bit client - server version mismatch. Using "${clientVersion}" Local version to communicate with "${_constants().BIT_VERSION}" on the Remove Server. Please update your Bit client.
For additional information: https://${_constants().BASE_DOCS_DOMAIN}/docs/latest-version.html`;

  if (localMajor > clientMajor) {
    if (clientMajor >= throwErrorFromServerSinceVersion) {
      // since version 14.x a new Error class has been created "OldClientVersion", use it.
      throw new (_exceptions().OldClientVersion)(oldClientVersionMessageAfterV14());
    }

    throw new Error(oldClientVersionMessageUntilV14);
  }
}

function isClientHasVersionBefore(version, clientVersion) {
  return semver().lt(clientVersion, version);
}