'use strict';

var Stream = require('stream')
  , util = require('util')
  , request = require('request')
  , debug = require('debug')('cartodb:import')
  , resources = require('./resources.json')
  , Mustache = require('mustache')
  , fs = require('fs')
  , _Promise = require('./promise')
  , requestUtil = require('./util/request')
  ;



debug = console.log;
/*
 * Constructor
 *
 * @config {Object} Connection params
 *
 * @api public
 */

function Import(config) {

  for(var i in config){
    this[i] = config[i];
  }

  this.import_api_url = this.import_api_url || Mustache.render(resources.import_api_url,config);

  return this;
}

/*
 * Inheritance
 */

util.inherits(Import, Stream);

Import.prototype.file = function(filePath, options) {

  var self = this;

  var promise = new _Promise();
  if(!filePath) {
    throw new TypeError('filePath should not be null');
  }

  if (!options) options = {};
  options.filePath = filePath;
  options.promise = promise;
  this._post('file',options);

  return promise;
};


Import.prototype.url = function(url, options) {

  var self = this;

  var promise = new _Promise();
  if(!url) {
    throw new TypeError('url should not be null');
  }

  if (!options) options = {};
  options.url = url;
  options.promise = promise;
  this._post('url',options);

  return promise;
};


Import.prototype.stream = function(stream, options) {

  var self = this;

  var promise = new _Promise();
  if(!stream) {
    throw new TypeError('stream should not be null');
  }

  if (!options) options = {};
  options.stream = stream
  options.promise = promise;

  var reqOptions = {
    method: 'POST',
    preambleCRLF: true,
    postambleCRLF: true,
    url: self.import_api_url,
    qs: {
      api_key: self.api_key,
      privacy: options.privacy
    },
    headers:{
      'content-type': 'multipart/form-data',
      accept:'*/*',
      expect:'100-continue'
    },
    formData: {
      //https://github.com/request/request/issues/1495
      value: stream,
      'options.filename': options.filename,
      'options.contentType': 'application/octet-stream'
    }
  };

  options.reqOptions = reqOptions;

  this._post('stream',options);

  return promise;
};


Import.prototype._post = function(type, options) {

  var self = this,
    req,
    reqOptions,
    defaultReqOptions = {
      url: self.import_api_url,
      json: true,
      qs: {
        api_key: self.api_key,
        privacy: options.privacy
      }
    };

  reqOptions = options.reqOptions || defaultReqOptions;

  debug(reqOptions)
  debug('POSTing your file to %s', self.import_api_url);

  req = reqOptions.method ? request(reqOptions, processResponse)
    : request.post(reqOptions, processResponse);

  if(type === 'file') {
    req.form().append('file', fs.createReadStream(options.filePath));
  }

  if(type === 'url') {
    req.form().append('url', options.url);
  }


  function processResponse(err, res, body) {
    if (err) {
      options.promise.emit('_error', err);
    } else {
      body = requestUtil.fixBody(body);

      debug(body);
      debug('Success, the item_queue_id is %s', body.item_queue_id);
      if(body.item_queue_id) {
        poll(body.item_queue_id);
      }
      else
        options.promise.emit('_error', 'body.item_queue_id undefined');
    }
  }


  function poll(queue_id) {
    debug('Polling to see if this file is finished importing...')
    setTimeout(function() {
    var pollUrl = self.import_api_url + '/' + queue_id;

      var getOptions = {
        url: pollUrl,
        json: true,
        qs: {
          api_key: self.api_key
        }
      };

      debug(getOptions);

      request.get(getOptions, processGetResponsefunction);


      function processGetResponsefunction(err, res, body) {

        body = requestUtil.fixBody(body);

        debug('statusCode: %s', res.statusCode)

        debug('Processing Import Status Response')
        debug(body);

        try {

          if( body.state == 'complete' ) {
            debug('It\'s finished! The table name is %s', body.table_name);
            options.promise.emit('done', body.table_name)

          } else if( body.state == 'failure') {
            debug('import failure')
            if(!body.get_error_text && !body.error_code)
              debug('body.get_error_text and body.error_code is undefined');

            options.promise.emit('_error', new Error(body.get_error_text || body.error_code));

          } else {
            debug('Not finished, trying again...');
            poll(queue_id); //recurse
          }
        }
        catch (err) {
          options.promise.emit('_error', err);
        }
      };

    },3000);
  }
}


/*
 * Exports the constructor
 */


module.exports = Import;

@@ -338,30 +338,8 @@
 ;%0A%0A%0A
-%0Adebug = console.log;%0A
 /*%0A 
@@ -1892,24 +1892,39 @@
 formData: %7B%0A
+      file:%7B%0A  
       //http
@@ -1972,16 +1972,18 @@
 5%0A      
+  
 value: s
@@ -1999,25 +1999,154 @@
     
-'
+  
 options
-.
+:%7B%0A          // MAIN ROADBLOCK: https://github.com/CartoDB/cartodb-nodejs/issues/57%0A          // knownLength: 7508273,%0A          
 filename
 ': o
@@ -2141,17 +2141,16 @@
 filename
-'
 : option
@@ -2171,17 +2171,13 @@
     
-'options.
+    '
 cont
@@ -2213,16 +2213,34 @@
 stream'%0A
+        %7D%0A      %7D%0A
     %7D%0A  
@@ -3015,25 +3015,24 @@
 .url);%0A  %7D%0A%0A
-%0A
   function p

save of Import.prototype.stream work