var request = require('request');
var pkgMeta = require('../package.json');

var BlockIo = module.exports = function (key) {
  this.key = key;
};

BlockIo.BASE_URL = 'https://block.io/api/v1/';
BlockIo.USER_AGENT = ['npm','block_io', pkgMeta.version].join(':');

BlockIo.VALID_CALL_METHODS = [
  'get_balance', 'withdraw', 'get_new_address', 'get_my_addresses',
  'get_address_received', 'get_address_by_label', 'get_address_balance', 'create_user',
  'get_users', 'get_user_balance', 'get_user_address',  'get_user_received',  'withdraw_from_user',
  'get_current_price', 'withdraw_from_label', 'withdraw_from_address', 'withdraw_from_labels',
  'withdraw_from_addresses', 'withdraw_from_users'
];

BlockIo.prototype._request = function (method, path, args, cb) {

  // currently only suporting GET
  if (method !== 'GET') return cb(new Error([method, 'not supported'].join(' ')));

  // validate args and add api_key
  if (!args || typeof(args) !== 'object') {
    args = { api_key: this.key };
  } else {
    args.api_key = this.key;
  }

  var opts = {
    method: method,
    url: [BlockIo.BASE_URL, path].join(''),
    qs: args,
    headers: {
      'Content-Type': 'application/json',
      'User-Agent': BlockIo.USER_AGENT
    }
  };

  return cb ? request(opts, BlockIo.parseResponse(cb)) : request(opts);

};

BlockIo.parseResponse = function (cb) {

  return function (err, res, body) {
    if (err) return cb(err);

    var errOut = null;
    var data = null;

    try {
      data = JSON.parse(body);
    } catch (ex) {
      errOut = ex;
    }

    return cb(errOut, data);
  };

};

BlockIo.prototype.validate_key = function (cb) {
  // Test if the key is valid by doing a simple balance check

  this._request('GET', 'get_balance', {}, function (err, doc) {
    var errOut = err || (doc.status === 'success') ? null : new Error('Error occurred validating key');
    return cb(errOut, (errOut === null));
  });

};

BlockIo._constructCallMethod = function (callMethod) {
  return function (args, cb) {

    // handle overload for function (cb), without args
    if (!cb && typeof(args) === 'function') {
      cb = args;
      args = {};
    }

    this._request('GET', callMethod, args, cb);
  };
};

// generate methods for each valid call method
BlockIo.VALID_CALL_METHODS.forEach(function (method) {
  BlockIo.prototype[method] = BlockIo._constructCallMethod(method);
});

@@ -115,15 +115,177 @@
 on (
-key)
+config) %7B%0A  if (typeof(config) === 'string') %7B%0A    this.key = config;%0A    this.port = '';%0A    this.server = '';%0A    this.version = BlockIo.DEFAULT_VERSION;%0A  %7D else
  %7B%0A
+  
   th
@@ -297,63 +297,294 @@
 y = 
-key;%0A%7D;%0A%0ABlockIo.BASE_URL = 'https://block.io/api/v1/';
+config.key;%0A    this.version = config.version %7C%7C BlockIo.DEFAULT_VERSION;%0A    this.server = config.server %7C%7C '';%0A    this.port = config.port %7C%7C '';%0A  %7D%0A%7D;%0A%0ABlockIo.DEFAULT_VERSION = 1;%0ABlockIo.HOST = 'block.io';%0A%0A// IF YOU EDIT THIS LIB, PLEASE BE A DARLING AND CHANGE THE USER AGENT :)
 %0ABlo
@@ -1086,16 +1086,323 @@
 rs'%0A%5D;%0A%0A
+BlockIo.prototype._constructURL = function (path) %7B%0A  return %5B%0A    'https://',%0A    this.server, (this.server) ? '.' : '', // eg: 'dev.'%0A    BlockIo.HOST, // block.io%0A    (this.port) ? ':' : '', this.port, // eg: :80%0A    '/api/v', (this.version).toString(10), '/', // eg: /api/v1/%0A    path%0A  %5D.join('');%0A%7D;%0A%0A
 BlockIo.
@@ -1783,40 +1783,31 @@
 rl: 
-%5BBlockIo.BASE_URL, 
+this._constructURL(
 path
-%5D.join(''
 ),%0A 

prepare lib for multi-version, multi-environment