var express = require('express'),
    request = require('superagent'),
    should = require('should'),
    csv = require('../../'),
    app = express.createServer();

app.get('/test/1', function(req, res) {
  res.csv([
    ['a', 'b', 'c']
  , ['d', 'e', 'f']
  ]);
});

app.get('/test/2', function(req, res) {
  res.csv([
    [ 'a', 'b', null ]
  ]);
});

app.get('/test/3', function(req, res) {
  res.csv([
    [ 'a', 'b', undefined ]
  ]);
});

app.get('/test/hexadecimal', function(req, res) {
  res.csv([
    ['0x0bea5f7a45740a05a96099e4f9b4a732dfe006', 'b']
  ])
})

app.get('/test/custom-headers', function(req, res) {
  res.csv([
    [ 'a', 'b', 'c' ]
  ], false, {
    'Access-Control-Allow-Origin': '*',
    'X-Powered-By': 'Good vibes'
  });
});

app.get('/test/status-code', function(req, res) {
  res.csv([
    [ 'a', 'b', undefined ]
  ], false, {
    'Access-Control-Allow-Origin': '*'
  }, 500);
});

app.get('/test/objectArray', function(req, res) {
  res.csv([
    { stringProp: "a", nullProp: null, undefinedProp: undefined },
    { stringProp: "b", nullProp: null, undefinedProp: undefined }
  ]);
});

app.get('/test/cyrillic/utf8', function(req, res) {
  res.csv([
    ['Привет', 'мир']
  ]);
});

app.get('/test/cyrillic/cp1251', function(req, res) {
  res.charset = "cp-1251";
  res.csv([
    ['Привет', 'мир']
  ]);
});

app.get('/test/separator', function(req, res) {
  csv.separator = '|'
  res.csv([
    { foo: "a", bar: 1 },
    { foo: "b", bar: 2}
  ], true);
});

app.listen(8383);

describe('csv-express', function() {

  it('should expose .separator', function() {
    csv.separator.should.be.type('string');
  });

  it('should expose .preventCast', function() {
    csv.preventCast.should.be.type('boolean');
  });

  it('should expose .ignoreNullOrUndefined', function() {
    csv.ignoreNullOrUndefined.should.be.type('boolean');
  });

});

describe('res.csv()', function() {

  it('should response csv', function(done) {
    request
      .get('http://127.0.0.1:8383/test/1')
      .end(function(error, res) {
        res.text.should.equal('"a","b","c"\r\n"d","e","f"\r\n');
        done();
      });
  });

  it('should response valid content-type', function(done) {
    request
      .get('http://127.0.0.1:8383/test/1')
      .end(function(error, res) {
        res.headers['content-type'].should.match(/^text\/csv/);
        done();
      });
  });

  it('should response csv includes ignored null', function(done) {
    request
      .get('http://127.0.0.1:8383/test/2')
      .end(function(error, res) {
        res.text.should.equal('"a","b",\r\n');
        done();
      });
  });

  it('should response csv includes ignored undefined', function(done) {
    request
      .get('http://127.0.0.1:8383/test/3')
      .end(function(error, res) {
        res.text.should.equal('"a","b",\r\n');
        done();
      });
  });

  it('should response csv includes null', function(done) {
    var prevOption = csv.ignoreNullOrUndefined;
    csv.ignoreNullOrUndefined = false;
    request
      .get('http://127.0.0.1:8383/test/2')
      .end(function(error, res) {
        csv.ignoreNullOrUndefined = prevOption;
        res.text.should.equal('"a","b","null"\r\n');
        done();
      });
  });

  it('should response csv includes undefined', function(done) {
    var prevOption = csv.ignoreNullOrUndefined;
    csv.ignoreNullOrUndefined = false;
    request
      .get('http://127.0.0.1:8383/test/3')
      .end(function(error, res) {
        csv.ignoreNullOrUndefined = prevOption;
        res.text.should.equal('"a","b","undefined"\r\n');
        done();
      });
  });

  it('should response correct hexadecimal', function(done) {
    request
      .get('http://127.0.0.1:8383/test/hexadecimal')
      .end(function(error, res) {
        res.text.should.equal('"0x0bea5f7a45740a05a96099e4f9b4a732dfe006","b"\r\n');
        done();
      });
  });

  it('should response tsv', function(done) {
    var prevSeparator = csv.separator;
    csv.separator = '\t';
    request
      .get('http://127.0.0.1:8383/test/1')
      .end(function(error, res) {
        csv.separator = prevSeparator;
        res.text.should.equal('"a"\t"b"\t"c"\r\n"d"\t"e"\t"f"\r\n');
        done();
      });
  });

  it('should response quoted csv', function(done) {
    var prevSetting = csv.preventCast;
    csv.preventCast = true;
    request
      .get('http://127.0.0.1:8383/test/1')
      .end(function(error, res) {
        csv.preventCast = prevSetting;
        res.text.should.equal('="a",="b",="c"\r\n="d",="e",="f"\r\n');
        done();
      });
  });

  it('should return custom response headers', function(done) {
    request
      .get('http://127.0.0.1:8383/test/custom-headers')
      .end(function(error, res) {
        res.headers['access-control-allow-origin'].should.equal('*');
        res.headers['x-powered-by'].should.equal('Good vibes');
        done();
      });
  });

  it('should return a custom error code', function(done) {
    request
      .get('http://127.0.0.1:8383/test/status-code')
      .end(function(error, res) {
        res.statusCode.should.equal(500);
        done();
      })
  });
});


describe('when given an array of objects', function() {
  describe('and ignoreNullOrUndefined is true', function() {
    var rows;

    beforeEach(function(done) {
      csv.ignoreNullOrUndefined = true;
      request
        .get('http://localhost:8383/test/objectArray')
        .end(function(error, res) {
          rows = res.text.split("\r\n");
          done();
        });
    });

    it('should include values that exist', function() {
      rows[0].split(",")[0].should.equal('"a"');
      rows[1].split(",")[0].should.equal('"b"');
    });

    it('should exclude null', function() {
      rows[0].split(",")[1].should.equal('');
      rows[0].split(",")[2].should.equal('');
    });

    it('should exclude undefined', function() {
      rows[0].split(",")[2].should.equal('');
      rows[1].split(",")[2].should.equal('');
    });
  });

  describe('and ignoreNullOrUndefined is false', function() {
    var rows;

    beforeEach(function(done) {
      csv.ignoreNullOrUndefined = false;
      request
        .get('http://127.0.0.1:8383/test/objectArray')
        .end(function(error, res) {
          rows = res.text.split("\r\n");
          done();
        });
    });

    it('should include values that exist', function() {
      rows[0].split(",")[0].should.equal('"a"');
      rows[1].split(",")[0].should.equal('"b"');
    });

    it('should include null', function() {
      rows[0].split(",")[1].should.equal('"null"');
      rows[1].split(",")[1].should.equal('"null"');
    });

    it('should include undefined', function() {
      rows[0].split(",")[2].should.equal('"undefined"');
      rows[1].split(",")[2].should.equal('"undefined"');
    });
  });
});


describe('when given cyrillyc data', function() {
  it('should response with utf-8 text', function(done) {
    request
      .get('http://127.0.0.1:8383/test/cyrillic/utf8')
      .end(function(error, res) {
        res.text.should.equal('"Привет","мир"\r\n');
        done();
      });
  });

  it('should response with cp-1251 text', function(done) {
    request
      .get('http://127.0.0.1:8383/test/cyrillic/cp1251')
      .end(function(error, res) {
        var text = new Buffer([0x22, 0xcf, 0xf0, 0xe8, 0xe2, 0xe5, 0xf2, 0x22, 0x2c, 0x22, 0xcc, 0xe8, 0xf0, 0x22, 0x0d, 0x0a]);
        res.text.should.equal(text.toString());
        done();
      });
  });
});

describe('when pipe-delimited', function() {
  it('should output a pipe-delimited file', function(done) {
    request
      .get('http://127.0.0.1:8383/test/separator')
      .end(function(error, res) {
        var responseBody = res.text.split('\r\n')
        var rows = responseBody.map(function(row) {
          return row.split('|')
        })
        // Make sure the header row uses the provided delimeter
        rows[0].length.should.equal(2)
        rows[0][0].should.equal('foo')
        done();
      });
  });
});
