'use strict';

var MAXTIME = Math.pow(2, 48) - 1;

var Node = {
  path: require('path'),
  process: process
};

var binding = require('./binding.node');

function assertPath(key, value) {
  if (typeof value !== 'string') {
    throw new Error(key + ' must be a string');
  }
  if (value.length === 0) {
    throw new Error(key + ' must not be empty');
  }
  if (value.indexOf('\u0000') !== -1) {
    throw new Error(key + ' must be a string without null bytes');
  }
}

function assertTime(key, value) {
  if (value === undefined) return;
  if (typeof value !== 'number') {
    throw new Error(key + ' must be a number or undefined');
  }
  if (Math.floor(value) !== value) {
    throw new Error(key + ' must be an integer');
  }
  if (value < 0) {
    throw new Error(key + ' must be a positive integer');
  }
  if (value > MAXTIME) {
    throw new Error(key + ' must not be more than ' + MAXTIME);
  }
}

function pathBuffer(path) {
  var pathLong = Node.path._makeLong(path);
  var buffer = Buffer.alloc(Buffer.byteLength(pathLong, 'utf-8') + 1);
  buffer.write(pathLong, 0, buffer.length - 1, 'utf-8');
  buffer[buffer.length - 1] = 0;
  if (buffer.indexOf(0) !== buffer.length - 1) {
    throw new Error('path must be a string without null bytes');
  }
  return buffer;
}

var Btime = {};

Btime.btime = function(path, btime) {
  assertPath('path', path);
  assertTime('btime', btime);
  if (btime === undefined) return;
  if (Node.process.platform === 'darwin' || Node.process.platform === 'win32') {
    let result = binding.btime(pathBuffer(path), btime);
    if (result !== 0) {
      throw new Error('(' + result + '), utimes(' + path + ')');
    }
  }
  // Linux does not support btime.
};

module.exports = Btime;
