// Generated by CoffeeScript 1.9.3
(function() {
  var _, net, optimist, punycode, util;

  _ = require('underscore');

  net = require('net');

  punycode = require('punycode');

  util = require('util');

  this.SERVERS = require('./servers.json');

  this.lookup = (function(_this) {
    return function(addr, options, done) {
      var data, parts, server, socket, tld;
      if (typeof done === 'undefined' && typeof options === 'function') {
        done = options;
        options = {};
      }
      _.defaults(options, {
        follow: 2
      });
      done = _.once(done);
      server = options.server;
      if (!server) {
        switch (true) {
          case _.contains(addr, ':'):
            done(new Error('lookup: IPv6 not supported'));
            return;
          case _.contains(addr, '@'):
            done(new Error('lookup: email addresses not supported'));
            return;
          case (addr.match(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/)) != null:
            server = _this.SERVERS['_']['ipv4'];
            break;
          default:
            tld = punycode.toASCII(addr);
            while (true) {
              server = _this.SERVERS[tld];
              if (!tld || server) {
                break;
              }
              tld = tld.replace(/^.+?(\.|$)/, '');
            }
        }
      }
      if (!server) {
        done(new Error('lookup: no whois server is known for this kind of object'));
        return;
      }
      if (typeof server === 'string') {
        parts = server.split(':');
        server = {
          host: parts[0],
          port: parts[1]
        };
      }
      _.defaults(server, {
        port: 43,
        query: "$addr\r\n"
      });
      socket = net.connect(server.port, server.host, function() {
        return socket.write(server.query.replace('$addr', punycode.toASCII(addr)));
      });
      socket.setEncoding('utf-8');
      if (options.timeout != null) {
        socket.setTimeout(options.timeout);
      }
      data = '';
      socket.on('data', function(chunk) {
        return data += chunk;
      });
      socket.on('timeout', function() {
        return done(new Error('lookup: timeout'));
      });
      socket.on('error', function(err) {
        return done(err);
      });
      return socket.on('close', function(err) {
        var match;
        if (options.follow > 0) {
          match = data.match(/(ReferralServer|Registrar Whois|Whois Server):\s*(r?whois:\/\/)?(.+)/);
          if (match != null) {
            options = _.extend({}, options, {
              follow: options.follow - 1,
              server: match[3]
            });
            _this.lookup(addr, options, function(err, parts) {
              if (err != null) {
                return done(err);
              }
              if (options.verbose) {
                return done(null, [
                  {
                    server: server,
                    data: data
                  }
                ].concat(parts));
              } else {
                return done(null, parts);
              }
            });
            return;
          }
        }
        if (options.verbose) {
          return done(null, [
            {
              server: server,
              data: data
            }
          ]);
        } else {
          return done(null, data);
        }
      });
    };
  })(this);

  if (module === require.main) {
    optimist = require('optimist').usage('$0 [options] address')["default"]('s', null).alias('s', 'server').describe('s', 'whois server')["default"]('f', 0).alias('f', 'follow').describe('f', 'number of times to follow redirects').boolean('v')["default"]('v', false).alias('v', 'verbose').describe('v', 'show verbose results').boolean('h')["default"]('h', false).alias('h', 'help').describe('h', 'display this help message');
    if (optimist.argv.h) {
      console.log(optimist.help());
      process.exit(0);
    }
    if (optimist.argv._[0] == null) {
      console.log(optimist.help());
      process.exit(1);
    }
    this.lookup(optimist.argv._[0], {
      server: optimist.argv.server,
      follow: optimist.argv.follow,
      verbose: optimist.argv.verbose
    }, (function(_this) {
      return function(err, data) {
        var i, len, part, results;
        if (err != null) {
          console.log(err);
          process.exit(1);
        }
        if (util.isArray(data)) {
          results = [];
          for (i = 0, len = data.length; i < len; i++) {
            part = data[i];
            console.log(part.server.host);
            console.log(part.data);
            results.push(console.log);
          }
          return results;
        } else {
          return console.log(data);
        }
      };
    })(this));
  }

}).call(this);
