// Generated by CoffeeScript 1.9.3
var FormData, JsonClient, buildOptions, fs, http, https, merge, mime, parseBody, playRequest, url;

FormData = require("form-data");

fs = require("fs");

url = require("url");

http = require('http');

https = require('https');

mime = require("mime");

merge = function(obj1, obj2) {
  var key, result;
  result = {};
  for (key in obj1) {
    result[key] = obj1[key];
  }
  if (obj2 != null) {
    for (key in obj2) {
      result[key] = obj2[key];
    }
  }
  return result;
};

buildOptions = function(clientOptions, clientHeaders, host, path, requestOptions) {
  var options, urlData;
  if (requestOptions !== {}) {
    options = merge(clientOptions, requestOptions);
  }
  if ((requestOptions != null) && requestOptions !== {} && requestOptions.headers) {
    options.headers = merge(clientHeaders, requestOptions.headers);
  } else {
    options.headers = merge(clientHeaders, {});
  }
  if (path[0] !== '/') {
    path = "/" + path;
  }
  urlData = url.parse(host);
  options.host = urlData.host.split(':')[0];
  options.port = urlData.port;
  options.protocol = urlData.protocol;
  options.path = path;
  if (urlData.protocol === 'https:') {
    options.requestFactory = https;
    options.rejectUnauthorized = false;
  } else {
    options.requestFactory = http;
  }
  return options;
};

parseBody = function(error, response, body, callback, parse) {
  var err, parsed;
  if (parse == null) {
    parse = true;
  }
  if (typeof body === "string" && body !== "" && parse) {
    try {
      parsed = JSON.parse(body);
    } catch (_error) {
      err = _error;
      if (error == null) {
        error = new Error("Parsing error : " + err.message + ", body= \n " + body);
      }
      parsed = body;
    }
  } else {
    parsed = body;
  }
  return callback(error, response, parsed);
};

playRequest = function(opts, data, callback, parse) {
  var encoding, req;
  if (parse == null) {
    parse = true;
  }
  if (typeof data === 'function') {
    callback = data;
    data = {};
  }
  if (data != null) {
    encoding = opts.encoding || 'utf8';
    if (typeof data === 'string') {
      data = new Buffer(data, encoding);
    } else if (!(data instanceof Buffer)) {
      data = new Buffer(JSON.stringify(data), encoding);
    }
    opts.headers['Content-Length'] = data.length;
  } else {
    delete opts.headers['Content-Length'];
    if (opts.headers['content-type'] === 'application/json') {
      delete opts.headers['content-type'];
    }
  }
  req = opts.requestFactory.request(opts, function(res) {
    var body;
    res.setEncoding('utf8');
    body = '';
    res.on('data', function(chunk) {
      return body += chunk;
    });
    return res.on('end', function() {
      return parseBody(null, res, body, callback, parse);
    });
  });
  req.on('error', function(err) {
    return callback(err);
  });
  if (data != null) {
    req.write(data);
  }
  return req.end();
};

module.exports = {
  newClient: function(url, options) {
    if (options == null) {
      options = {};
    }
    return new JsonClient(url, options);
  },
  get: function(opts, data, callback, parse) {
    opts.method = "GET";
    return playRequest(opts, data, callback, parse);
  },
  del: function(opts, data, callback, parse) {
    opts.method = "DELETE";
    return playRequest(opts, data, callback, parse);
  },
  post: function(opts, data, callback, parse) {
    opts.method = "POST";
    return playRequest(opts, data, callback, parse);
  },
  put: function(opts, data, callback, parse) {
    opts.method = "PUT";
    return playRequest(opts, data, callback, parse);
  },
  patch: function(opts, data, callback, parse) {
    opts.method = "PATCH";
    return playRequest(opts, data, callback, parse);
  },
  head: function(opts, data, callback) {
    opts.method = "HEAD";
    return playRequest(opts, data, callback);
  }
};

JsonClient = (function() {
  function JsonClient(host1, options1) {
    var ref;
    this.host = host1;
    this.options = options1 != null ? options1 : {};
    this.headers = (ref = this.options.headers) != null ? ref : {};
    this.headers['accept'] = 'application/json';
    this.headers['user-agent'] = "request-json/1.0";
    this.headers['content-type'] = 'application/json';
  }

  JsonClient.prototype.setBasicAuth = function(username, password) {
    var basicCredentials, credentials;
    credentials = username + ":" + password;
    basicCredentials = new Buffer(credentials).toString('base64');
    return this.headers["authorization"] = "Basic " + basicCredentials;
  };

  JsonClient.prototype.setToken = function(token) {
    return this.headers["x-auth-token"] = token;
  };

  JsonClient.prototype.get = function(path, options, callback, parse) {
    var opts;
    if (parse == null) {
      parse = true;
    }
    if (typeof options === 'function') {
      if (typeof callback === 'boolean') {
        parse = callback;
      }
      callback = options;
      options = {};
    }
    opts = buildOptions(this.options, this.headers, this.host, path, options);
    return module.exports.get(opts, null, callback, parse);
  };

  JsonClient.prototype.post = function(path, data, options, callback, parse) {
    var opts;
    if (parse == null) {
      parse = true;
    }
    if (typeof options === 'function') {
      if (typeof callback === 'boolean') {
        parse = callback;
      }
      callback = options;
      options = {};
    }
    if (typeof data === 'function') {
      if (typeof options === 'boolean') {
        parse = options;
      }
      callback = data;
      data = {};
      options = {};
    }
    opts = buildOptions(this.options, this.headers, this.host, path, options);
    return module.exports.post(opts, data, callback);
  };

  JsonClient.prototype.put = function(path, data, options, callback, parse) {
    var opts;
    if (parse == null) {
      parse = true;
    }
    if (typeof options === 'function') {
      if (typeof callback === 'boolean') {
        parse = callback;
      }
      callback = options;
      options = {};
    }
    opts = buildOptions(this.options, this.headers, this.host, path, options);
    return module.exports.put(opts, data, callback, parse);
  };

  JsonClient.prototype.patch = function(path, data, options, callback, parse) {
    var opts;
    if (parse == null) {
      parse = true;
    }
    if (typeof options === 'function') {
      if (typeof callback === 'boolean') {
        parse = callback;
      }
      callback = options;
      options = {};
    }
    opts = buildOptions(this.options, this.headers, this.host, path, options);
    return module.exports.patch(opts, data, callback, parse);
  };

  JsonClient.prototype.del = function(path, options, callback, parse) {
    var opts;
    if (parse == null) {
      parse = true;
    }
    if (typeof options === 'function') {
      if (typeof callback === 'boolean') {
        parse = callback;
      }
      callback = options;
      options = {};
    }
    opts = buildOptions(this.options, this.headers, this.host, path, options);
    return module.exports.del(opts, null, callback, parse);
  };

  JsonClient.prototype["delete"] = function(path, options, callback, parse) {
    if (parse == null) {
      parse = true;
    }
    return this.del(path, options, callback, parse);
  };

  JsonClient.prototype.head = function(path, data, options, callback, parse) {
    var opts;
    if (parse == null) {
      parse = true;
    }
    if (typeof options === 'function') {
      if (typeof callback === 'boolean') {
        parse = callback;
      }
      callback = options;
      options = {};
    }
    opts = buildOptions(this.options, this.headers, this.host, path, options);
    return module.exports.head(opts, null, callback);
  };

  JsonClient.prototype.sendFile = function(path, files, data, callback, parse) {
    var att, file, form, i, index, len, options;
    if (parse == null) {
      parse = true;
    }
    if (typeof data === "function") {
      callback = data;
    }
    form = new FormData();
    if (typeof data !== "function") {
      for (att in data) {
        form.append(att, data[att]);
      }
    }
    if (typeof files === "string") {
      form.append("file", fs.createReadStream(files));
    } else if (!Array.isArray(files)) {
      files.path = files.path || "useless_But_Required_String";
      form.append("file", files);
    } else {
      index = 0;
      for (i = 0, len = files.length; i < len; i++) {
        file = files[i];
        index++;
        if (typeof file === "string") {
          form.append("file" + index, fs.createReadStream(file));
        } else {
          form.append("file" + index, file);
        }
      }
    }
    options = buildOptions(this.options, this.headers, this.host, path, {
      method: 'POST'
    });
    delete options.headers['content-type'];
    if (options.requestFactory === https) {
      options.protocol = 'https:';
    }
    delete options.requestFactory;
    return form.submit(options, function(err, res) {
      var body;
      if (err) {
        return callback(err);
      }
      res.setEncoding('utf8');
      body = '';
      res.on('data', function(chunk) {
        return body += chunk;
      });
      return res.on('end', function() {
        return parseBody(null, res, body, callback, parse);
      });
    });
  };

  JsonClient.prototype.putFile = function(path, file, callback, parse) {
    var fileStream, opts, req, reqStream;
    if (parse == null) {
      parse = true;
    }
    opts = buildOptions(this.options, this.headers, this.host, path, {
      method: 'PUT'
    });
    if (typeof file === "string") {
      opts.headers['content-type'] = mime.lookup(file);
      fileStream = fs.createReadStream(file);
    } else {
      fileStream = file;
    }
    req = opts.requestFactory.request(opts, function(res) {
      var body;
      res.setEncoding('utf8');
      body = '';
      res.on('data', function(chunk) {
        return body += chunk;
      });
      return res.on('end', function() {
        return parseBody(null, res, body, callback, parse);
      });
    });
    req.on('error', function(err) {
      return callback(err);
    });
    reqStream = fileStream.pipe(req);
    return {
      reqStream: reqStream,
      fileStream: fileStream
    };
  };

  JsonClient.prototype.saveFile = function(path, filePath, callback) {
    var options, opts, req;
    options = {};
    opts = buildOptions(this.options, this.headers, this.host, path, options);
    opts.option = "GET";
    req = opts.requestFactory.request(opts, function(res) {
      var fileStream;
      fileStream = fs.createWriteStream(filePath);
      res.pipe(fileStream);
      return fileStream.on('finish', function() {
        return callback(null, res);
      });
    });
    req.on('error', function(err) {
      return callback(err);
    });
    return req.end();
  };

  JsonClient.prototype.saveFileAsStream = function(path, callback) {
    var options, opts, req;
    options = {};
    opts = buildOptions(this.options, this.headers, this.host, path, options);
    opts.option = "GET";
    req = opts.requestFactory.request(opts, function(res) {
      return callback(null, res);
    });
    req.on('error', function(err) {
      return callback(err);
    });
    return req.end();
  };

  return JsonClient;

})();

module.exports.JsonClient = JsonClient;
