const {
  hideStackFrames,
} = require('./errors');

const {
  isUint32,
  parseFileMode,
  validateBuffer,
  validateInteger,
  validateInt32
} = require('./validators');


function toPathIfFileURL(fileURLOrPath) {
  if (fileURLOrPath instanceof URL) {
    return fileURLOrPath.pathname
  }
  return fileURLOrPath;
}

const {
  isUint8Array,
} = require("./util/types.js");

// Check if the path contains null types if it is a string nor Uint8Array,
// otherwise return silently.
const nullCheck = hideStackFrames((path, propName, throwError = true) => {
  const pathIsString = typeof path === 'string';
  const pathIsUint8Array = isUint8Array(path);

  // We can only perform meaningful checks on strings and Uint8Arrays.
  if ((!pathIsString && !pathIsUint8Array) ||
      (pathIsString && !path.includes('\u0000')) ||
      (pathIsUint8Array && !path.includes(0))) {
    return;
  }

  const err = new ERR_INVALID_ARG_VALUE(
    propName,
    path,
    'must be a string or Uint8Array without null bytes'
  );
  if (throwError) {
    throw err;
  }
  return err;
})

const validatePath = hideStackFrames((path, propName = 'path') => {
  if (typeof path !== 'string' && !isUint8Array(path)) {
    throw new ERR_INVALID_ARG_TYPE(propName, ['string', 'Buffer', 'URL'], path);
  }

  const err = nullCheck(path, propName, false);

  if (err !== undefined) {
    throw err;
  }
});

const getValidatedPath = hideStackFrames((fileURLOrPath, propName = 'path') => {
  const path = toPathIfFileURL(fileURLOrPath);
  validatePath(path, propName);
  return path;
});

module.exports = {
  validatePath,
  getValidatedPath,
  nullCheck,
}
