"use strict";

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

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Prototype = void 0;

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

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

var _tsFns = require("ts-fns");

var Prototype = /*#__PURE__*/function () {
  function Prototype() {
    var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    (0, _classCallCheck2.default)(this, Prototype);
    this.name = options.name;
    this.validate = options.validate;
  }

  (0, _createClass2.default)(Prototype, [{
    key: "toString",
    value: function toString() {
      return this.name;
    }
  }]);
  return Prototype;
}();

exports.Prototype = Prototype;
var prototypes = [];

Prototype.register = function (proto, validate) {
  var item = prototypes.find(function (item) {
    return item.proto === proto;
  });

  if (item) {
    item.validate = validate;
  } else {
    prototypes.push({
      proto: proto,
      validate: validate
    });
  }
};

Prototype.unregister = function () {
  if (arguments.length === 0) {
    prototypes.length = 0;
    return;
  }

  var proto = arguments.length <= 0 ? undefined : arguments[0];

  for (var i = 0, len = prototypes.length; i < len; i++) {
    var item = prototypes[i];

    if (item.proto === proto) {
      prototypes.splice(i, 1);
      break;
    }
  }
};

var find = function find(proto) {
  return prototypes.find(function (item) {
    return item.proto === proto;
  });
};

Prototype.is = function (proto) {
  return {
    // Prototype.is(Number).existing()
    existing: function existing() {
      return (0, _tsFns.isNaN)(proto) || (0, _tsFns.isInstanceOf)(proto, RegExp) || !!find(proto) || (0, _tsFns.isInstanceOf)(proto, Prototype) || (0, _tsFns.isConstructor)(proto) || (0, _tsFns.isInheritedOf)(proto, Prototype);
    },
    // Prototype.is(Number).typeof(10)
    typeof: function _typeof(value) {
      if ((0, _tsFns.isInstanceOf)(proto, Prototype)) {
        return proto.validate(value);
      }

      if ((0, _tsFns.isInheritedOf)(proto, Prototype)) {
        return new proto().validate(value);
      }

      var item = find(proto);

      if (item) {
        return item.validate(value);
      }

      if ((0, _tsFns.isNaN)(proto)) {
        return (0, _tsFns.isNaN)(value);
      }

      if ((0, _tsFns.isInstanceOf)(proto, RegExp)) {
        return (0, _tsFns.isString)(value) && proto.test(value);
      }

      if ((0, _tsFns.isConstructor)(proto)) {
        return (0, _tsFns.isInstanceOf)(value, proto) || (0, _tsFns.isConstructor)(value) && (0, _tsFns.isInheritedOf)(value, proto);
      }

      return false;
    },
    // Prototype.is(10).equal(10)
    equal: function equal(value) {
      return proto === value;
    }
  };
};

Prototype.register(Number, _tsFns.isNumber);
Prototype.register(String, _tsFns.isString);
Prototype.register(Boolean, _tsFns.isBoolean);
Prototype.register(Object, _tsFns.isObject);
Prototype.register(Array, _tsFns.isArray);
Prototype.register(Function, _tsFns.isFunction);
Prototype.register(Symbol, _tsFns.isSymbol);
Prototype.register(Infinity, _tsFns.isInfinite);