import { NzSafeAny } from 'ng-zorro-antd/core/types';

function getTag(value: NzSafeAny): string {
  const toStr = Object.prototype.toString;
  if (value === null) {
    return value === undefined ? '[object Undefined]' : '[object Null]';
  }
  return toStr.call(value);
}

export function isString(value: NzSafeAny): boolean {
  const type = typeof value;
  return type === 'string' || (type === 'object' && value != null && !Array.isArray(value) && getTag(value) === '[object String]');
}


/** Used as references for various `Number` constants. */
const INFINITY = 1 / 0;

/**
 * Converts `value` to a string. An empty string is returned for `null`
 * and `undefined` values. The sign of `-0` is preserved.
 *
 * @param  value The value to convert.
 * @returns  Returns the converted string.
 * @example
 *
 * toString(null)
 * // => ''
 *
 * toString(-0)
 * // => '-0'
 *
 * toString([1, 2, 3])
 * // => '1,2,3'
 */
export function toString(value: NzSafeAny): string {
  if (value == null) {
    return '';
  }
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value === 'string') {
    return value;
  }
  if (Array.isArray(value)) {
    // Recursively convert values (susceptible to call stack limits).
    return `${value.map((other) => other == null ? other : toString(other))}`;
  }
  const result = `${value}`;
  return (result === '0' && (1 / value) === -INFINITY) ? '-0' : result;
}

export default toString;
