var assert = require('assert');
var pf = require('point-free');
var pg = require('./index').configure('postgres://postgres@localhost/pg_bricks');
if (process.env.PGBRICKS_TEST_NATIVE) {
    pg = pg.native;
}


var INITIAL = [
    {title: 'apple', price: 10},
    {title: 'orange', price: 20},
]


describe('pg-bricks', function () {
    before(function (done) {
        // Create test database and fill a test data
        var pgsu = require('./index').configure('postgres://postgres@localhost/postgres');

        pf.serial(
            pgsu.raw('drop database if exists pg_bricks').run,
            pgsu.raw('create database pg_bricks').run,
            pg.raw('create table item (id serial, title text, price int)').run,
            pg.insert('item', INITIAL).run
        )(function (err, res) {
            done(err);
        })
    })


    it('should run query', function (done) {
        pg.raw('select 42 as x').run(function (err, res) {
            assert.ifError(err);
            assert.equal(res.command, 'SELECT');
            assert.deepEqual(res.rows, [{x: 42}]);
            done();
        })
    })

    it('should support sql-bricks', function (done) {
        pf.waterfall(
            pg.select('title', 'price').from('item').run,
            function (res, callback) {
                assert.deepEqual(res.rows, INITIAL);
                done();
            }
        )(done)
    })

    describe('Accessors', function () {
        it('should provide .rows', function (done) {
            pf.waterfall(
                pg.select('title', 'price').from('item').rows,
                function (rows, callback) {
                    assert.deepEqual(rows, INITIAL);
                    done();
                }
            )(done)
        })

        it('should provide .col', function (done) {
            pf.waterfall(
                pg.select('title').from('item').col,
                function (col, callback) {
                    assert.deepEqual(col, ['apple', 'orange']);
                    done();
                }
            )(done)
        })

        it('should provide .val', function (done) {
            pf.waterfall(
                pg.select('price').from('item').where({title: 'apple'}).val,
                function (price, callback) {
                    assert.equal(price, 10);
                    done();
                }
            )(done)
        })

        it('should provide .val on .raw', function (done) {
            pf.waterfall(
                pg.raw('select price from item where title = $1', ['apple']).val,
                function (price, callback) {
                    assert.equal(price, 10);
                    done();
                }
            )(done)
        })
    })

    describe('Promises', function () {
        it('should return promise', function () {
            var res = pg.raw('select 42 as x').run();
            assert(res instanceof Promise);
        })

        it('should work with raw', function () {
            return pg.raw('select 42 as x').run().then(function (data) {
                assert.deepEqual(data.rows, [{x: 42}])
            })
        })

        it('should support sql-bricks', function () {
            return pg.raw('select 42 as x').run().then(function (data) {
                assert.deepEqual(data.rows, [{x: 42}])
            })
        })

        it('should work with accessors', function () {
            pg.select('title').from('item').col().then(function (col) {
                assert.deepEqual(col, ['apple', 'orange']);
            })
        })
    })

    describe('Streaming', function () {
        it('should return EventEmitter', function (done) {
            var query = pg.select('title', 'price').from('item').where({price: 10}).run();

            query.on('row', function (row) {
                assert.deepEqual(row, {"title": "apple", "price": 10})
            });
            query.on('end', function () {
                done();
            })
        })

        it('should pipe', function (done) {
            var query = pg.raw('select title, price from item where price = 10').run();
            var store = new StoreStream();

            query.pipe(store);
            query.on('end', function () {
                assert.deepEqual(store._store, [{"title": "apple", "price": 10}])
                done();
            })
        })

        it('should pipe from client', function (done) {
            pg.run(function (client, callback) {
                var query = client.raw('select title, price from item where price = 10').run();
                var store = new StoreStream();
                query.pipe(store);
                query.on('end', function () {
                    assert.deepEqual(store._store, [{"title": "apple", "price": 10}])
                    callback();
                })
            }, done)
        })
    })
})


// Helper stream
var stream = require('stream')
var util   = require('util');

util.inherits(StoreStream, stream.Writable);
function StoreStream(options) {
    stream.Writable.call(this, options);
    this._store = [];
}

StoreStream.prototype.write = function (chunk, encoding, callback) {
    this._store.push(chunk);
};

@@ -3409,32 +3409,39 @@
 ) %7B%0A            
+return 
 pg.select('title
@@ -3432,32 +3432,38 @@
 pg.select('title
+,price
 ').from('item').
@@ -3466,13 +3466,50 @@
 m').
-col()
+where(%7Btitle: 'apple'%7D).row()%0A            
 .the
@@ -3520,19 +3520,19 @@
 nction (
-col
+row
 ) %7B%0A    
@@ -3564,32 +3564,40 @@
 ual(
-col, %5B'apple', 'orange'%5D
+row, %7Btitle: 'apple', price: 10%7D
 );%0A 

Test .row() and fix promise/accessor test