var assert = require('chai').assert;
var nodemock = require('nodemock');
var Deferred = require('jsdeferred').Deferred;
var express = require('express');

var utils = require('./test-utils');

var adapter = require('../index');
var command = require('../lib/adapter/command');

suite('Adaption for express application', function() {
  var testRestPlugin = {
    api: new command.HTTPCommand({
      path: '/path/to/api',
      requestConverter: function(event, request) { return [event, 'api requested']; },
      responseConverter: function(event, data) { return [event, 'api OK']; }
    })
  };
  var testSocketPlugin = {
    api: new command.SocketRequestResponse({
      requestConverter: function(event, data) { return [event, 'api requested']; },
      responseConverter: function(event, data) { return [event, 'api OK']; }
    })
  };

  suite('REST API registeration', function() {
    var backend;
    var connection;
    var application;
    var server;

    setup(function(done) {
      utils.setupApplication()
        .next(function(result) {
          backend = result.backend;
          server = result.server;
          connection = result.connection;
          application = result.application;
          done();
        });
    });

    teardown(function() {
      utils.teardownApplication({ backend:    backend,
                                  server:     server,
                                  connection: connection });
    });

    test('to the document root', function(done) {
      application.droonga({
        prefix:     '',
        connection: connection,
        plugins:    [testRestPlugin, testSocketPlugin]
      });

      backend.reserveResponse(function(request) {
        return utils.createReplyPacket(request,
                                       {
                                         statusCode: 200,
                                         body:       'API response',
                                       });
      });

      utils.get('/path/to/api')
        .next(function(response) {
          backend.assertReceived([{ type: 'api',
                                    body: 'api requested' }]);
          assert.deepEqual(response,
                           { statusCode: 200,
                             body:       JSON.stringify('api OK') });
          done();
        })
        .error(function(error) {
          done(error);
        });
    });

    test('under specified path', function(done) {
      application.droonga({
        prefix:     '/path/to/droonga',
        connection: connection,
        plugins:    [testRestPlugin, testSocketPlugin]
      });

      var responseBody;
      utils.get('/path/to/droonga/path/to/api')
        .next(function(response) {
          responseBody = response.body;
        });

      Deferred
        .wait(0.01)
        .next(function() {
          backend.assertReceived([{ type: 'api',
                                    body: 'api requested' }]);

          return backend.sendResponse(backend.getMessages()[0],
                                      'api.result',
                                      'api OK?');
        })
        .wait(0.01)
        .next(function() {
          assert.equal(responseBody, JSON.stringify('api OK'));
          done();
        })
        .error(function(error) {
          done(error);
        });
    });
  });

  suite('Socket.IO API registeration', function() {
    var application;
    var connection;
    var server;
    var clientSocket;
    var backend;

    setup(function(done) {
      utils.setupApplication()
        .next(function(result) {
          backend = result.backend;
          server = result.server;
          connection = result.connection;
          application = result.application;
          done();
        });
    });

    teardown(function() {
      if (clientSocket) {
        clientSocket.disconnect();
        clientSocket = undefined;
      }
      utils.teardownApplication({ backend:    backend,
                                  server:     server,
                                  connection: connection });
    });

    test('request-response', function(done) {
      application.droonga({
        connection: connection,
        server:     server,
        plugins:    [testRestPlugin, testSocketPlugin]
      });

      var mockedReceiver;
      utils.createClientSocket()
        .next(function(newClientSocket) {
          clientSocket = newClientSocket;
          clientSocket.emit('api', 'request');
        })
        .wait(0.01)
        .next(function() {
          backend.assertReceived([{ type: 'api',
                                    body: 'api requested' }]);

          mockedReceiver = nodemock
            .mock('receive')
              .takes('api OK');
          clientSocket.on('api.result', function(data) {
            mockedReceiver.receive(data);
          });

          return backend.sendResponse(backend.getMessages()[0],
                                      'api.result',
                                      'api OK?');
        })
        .wait(0.01)
        .next(function() {
          mockedReceiver.assertThrows();
          done();
        })
        .error(function(error) {
          done(error);
        });
    });
  });
});


@@ -420,32 +420,25 @@
 ,%0A      
-r
+onR
 equest
-Converter
 : functi
@@ -444,39 +444,60 @@
 ion(
-event, request) %7B return %5Bevent
+request, connection) %7B%0A        connection.emit('api'
 , 'a
@@ -501,34 +501,40 @@
  'api requested'
-%5D;
+);%0A     
  %7D,%0A      respon
@@ -527,33 +527,26 @@
 ,%0A      
-r
+onR
 esponse
-Converter
 : functi
@@ -552,48 +552,70 @@
 ion(
-event, data) %7B return %5Bevent, 'api OK'%5D;
+data, response) %7B%0A        response.jsonp('api OK', 200);%0A     
  %7D%0A 
@@ -707,24 +707,17 @@
     
-r
+onR
 equest
-Converter
 : fu
@@ -727,36 +727,57 @@
 ion(
-event, data) %7B return %5Bevent
+data, connection) %7B%0A        connection.emit('api'
 , 'a
@@ -789,18 +789,24 @@
 quested'
-%5D;
+);%0A     
  %7D,%0A    
@@ -811,25 +811,18 @@
     
-r
+onR
 esponse
-Converter
 : fu
@@ -832,36 +832,49 @@
 ion(
-event, data) %7B return %5Bevent
+data, socket) %7B%0A        socket.emit('api'
 , 'a
@@ -883,10 +883,16 @@
  OK'
-%5D;
+);%0A     
  %7D%0A 

Update tests for the new style of command definitions