import { RX_NUMBER } from '../constants/regex';
import { File } from '../constants/safe-types';

// --- Convenience inspection utilities ---

const toType = value => typeof value;
const toRawType = value => Object.prototype.toString.call(value).slice(8, -1);
const toRawTypeLC = value => toRawType(value).toLowerCase();
const isUndefined = value => value === undefined;
const isNull = value => value === null;
const isUndefinedOrNull = value => isUndefined(value) || isNull(value);
const isFunction = value => toType(value) === 'function';
const isBoolean = value => toType(value) === 'boolean';
const isString = value => toType(value) === 'string';
const isNumber = value => toType(value) === 'number';
const isNumeric = value => RX_NUMBER.test(String(value));
const isPrimitive = value => isBoolean(value) || isString(value) || isNumber(value);
const isArray = value => Array.isArray(value);

// Quick object check
// This is primarily used to tell Objects from primitive values
// when we know the value is a JSON-compliant type
// Note object could be a complex type like array, Date, etc.
const isObject = obj => obj !== null && typeof obj === 'object';

// Strict object type check
// Only returns true for plain JavaScript objects
const isPlainObject = obj => Object.prototype.toString.call(obj) === '[object Object]';
const isDate = value => value instanceof Date;
const isEvent = value => value instanceof Event;
const isFile = value => value instanceof File;
const isRegExp = value => toRawType(value) === 'RegExp';
const isPromise = value => !isUndefinedOrNull(value) && isFunction(value.then) && isFunction(value.catch);

export { isArray, isBoolean, isDate, isEvent, isFile, isFunction, isNull, isNumber, isNumeric, isObject, isPlainObject, isPrimitive, isPromise, isRegExp, isString, isUndefined, isUndefinedOrNull, toRawType, toRawTypeLC, toType };
