//
// Test binary messages on websockets.
// Only works on slimer for now, due to old websocket impl in phantomjs.
//

casper.notebook_test(function () {
    if (!this.slimerjs) {
        console.log("Can't test binary websockets on phantomjs.");
        return;
    }
    // create EchoBuffers target on js-side.
    // it just captures and echos comm messages.
    this.then(function () {
        var success = this.evaluate(function () {
            IPython._msgs = [];
        
            var EchoBuffers = function(comm) {
                this.comm = comm;
                this.comm.on_msg($.proxy(this.on_msg, this));
            };

            EchoBuffers.prototype.on_msg = function (msg) {
                IPython._msgs.push(msg);
                this.comm.send(msg.content.data, {}, {}, msg.buffers);
            };

            IPython.notebook.kernel.comm_manager.register_target("echo", function (comm) {
                return new EchoBuffers(comm);
            });
        
            return true;
        });
        this.test.assertEquals(success, true, "Created echo comm target");
    });

    // Create a similar comm that captures messages Python-side
    this.then(function () {
        var index = this.append_cell([
            "import os",
            "from IPython.kernel.comm import Comm",
            "comm = Comm(target_name='echo')",
            "msgs = []",
            "def on_msg(msg):",
            "    msgs.append(msg)",
            "comm.on_msg(on_msg)"
        ].join('\n'), 'code');
        this.execute_cell(index);
    });
    
    // send a message with binary data
    this.then(function () {
        var index = this.append_cell([
            "buffers = [b'\\xFF\\x00', b'\\x00\\x01\\x02']",
            "comm.send(data='hi', buffers=buffers)"
        ].join('\n'), 'code');
        this.execute_cell(index);
    });
    
    // wait for capture
    this.waitFor(function () {
        return this.evaluate(function () {
            return IPython._msgs.length > 0;
        });
    });
    
    // validate captured buffers js-side
    this.then(function () {
        var msgs = this.evaluate(function () {
            return IPython._msgs;
        });
        this.test.assertEquals(msgs.length, 1, "Captured comm message");
        var buffers = msgs[0].buffers;
        this.test.assertEquals(buffers.length, 2, "comm message has buffers");
        
        // extract attributes to test in evaluate,
        // because the raw DataViews can't be passed across
        var buf_info = function (index) {
            var buf = IPython._msgs[0].buffers[index];
            var data = {};
            data.byteLength = buf.byteLength;
            data.bytes = [];
            for (var i = 0; i < data.byteLength; i++) {
                data.bytes.push(buf.getUint8(i));
            }
            return data;
        };
        
        buf0 = this.evaluate(buf_info, 0);
        buf1 = this.evaluate(buf_info, 1);
        this.test.assertEquals(buf0.byteLength, 2, 'buf[0] has correct size');
        this.test.assertEquals(buf0.bytes, [255, 0], 'buf[0] has correct bytes');
        this.test.assertEquals(buf1.byteLength, 3, 'buf[1] has correct size');
        this.test.assertEquals(buf1.bytes, [0, 1, 2], 'buf[1] has correct bytes');
    });
    
    // validate captured buffers Python-side
    this.then(function () {
        var index = this.append_cell([
            "assert len(msgs) == 1, len(msgs)",
            "bufs = msgs[0]['buffers']",
            "assert len(bufs) == len(buffers), bufs",
            "assert bufs[0].bytes == buffers[0], bufs[0].bytes",
            "assert bufs[1].bytes == buffers[1], bufs[1].bytes",
            "1",
        ].join('\n'), 'code');
        this.execute_cell(index);
        this.wait_for_output(index);
        this.then(function () {
            var out = this.get_output_cell(index);
            this.test.assertEquals(out['text/plain'], '1', "Python received buffers");
        });
    });
});
