#!/usr/bin/env node
// -*- mode: js -*-
// Copyright 2011 Mark Cavage.  All rights reserved.

var fs = require('fs');
var path = require('path');

var dashdash = require('dashdash');

var ldap = require('../lib/index');
var Logger = require('bunyan');


///--- Globals

var opts = [
  {
    names: ['attribute', 'a'],
    type: 'string',
    help: 'Attribute to modify',
    helpArg: 'ATTR'
  },
  {
    names: ['value', 'v'],
    type: 'arrayOfString',
    help: 'Desired value',
    helpArg: 'VAL'
  },
  {
    names: ['type', 't'],
    type: 'string',
    help: 'Attribute type',
    helpArg: 'TYPE'
  },
  { group: 'General options' },
  {
    names: ['help', 'h'],
    type: 'bool',
    help: 'Print this help and exit.'
  },
  {
    names: ['debug', 'd'],
    type: 'integer',
    help: 'Set debug level <0-2>',
    helpArg: 'LEVEL'
  },
  { group: 'Connection Options' },
  {
    names: ['url', 'u'],
    type: 'string',
    help: 'LDAP server URL',
    helpArg: 'URL',
    default: 'ldap://127.0.0.1:389'
  },
  {
    names: ['binddn', 'D'],
    type: 'string',
    help: 'Bind DN',
    helpArg: 'BIND_DN',
    default: ''
  },
  {
    names: ['password', 'w'],
    type: 'string',
    help: 'Bind password',
    helpArg: 'PASSWD',
    default: ''
  },
  {
    names: ['insecure', 'i'],
    type: 'bool',
    env: 'LDAPJS_TLS_INSECURE',
    help: 'Disable SSL certificate verification',
    default: false
  }
];
var parser = dashdash.createParser({options: opts});



///--- Helpers

function usage(code, message) {
  var msg = (message ? message + '\n' : '') +
    'Usage: ' + path.basename(process.argv[1]) + ' [OPTIONS] DN\n\n' +
    parser.help({includeEnv: true});

  process.stderr.write(msg + '\n');
  process.exit(code);
}


function perror(err) {
  if (parsed.debug) {
    process.stderr.write(err.stack + '\n');
  } else {
    process.stderr.write(err.message + '\n');
  }
  process.exit(1);
}



///--- Mainline

var logLevel = 'info';
var parsed;

try {
  parsed = parser.parse(process.argv);
} catch (e) {
  usage(1, e.toString());
}

if (parsed.help)
  usage(0);

if (parsed._args.length < 1)
  usage(1, 'DN required');
try {
  parsed._args.forEach(function (dn) {
    ldap.parseDN(dn);
  });
} catch (e) {
  usage(1, e.toString());
}

if (!parsed.type)
  parsed.type = 'replace';
if (!parsed.attribute || !Array.isArray(parsed.value))
  usage(1, 'attribute and value required');

if (parsed.debug)
  logLevel = (parsed.debug > 1 ? 'trace' : 'debug');

var log = new Logger({
    name: 'ldapjs',
    component: 'client',
    stream: process.stderr,
    level: logLevel
});

var client = ldap.createClient({
  url: parsed.url,
  log: log,
  strictDN: false,
  tlsOptions: {
    rejectUnauthorized: !parsed.insecure
  }
});

client.on('error', function (err) {
  perror(err);
});

client.bind(parsed.binddn, parsed.password, function (err, res) {
  if (err)
    perror(err);

  var finished = 0;
  var mod = {};
  mod[parsed.attribute] = [];
  parsed.value.forEach(function (v) {
    mod[parsed.attribute].push(v);
  });
  var change = new ldap.Change({
    type: parsed.type,
    modification: mod
  });

  function callback(err) {
    if (err)
      perror(err);

    if (++finished === parsed._args.length) {
      client.unbind(function () {
        return;
      });
    }
  }

  parsed._args.forEach(function (dn) {
    client.modify(dn, change, callback);
  });
});
