var assert = require('chai').assert;
var nodemock = require('nodemock');

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

var express = require('express');
var restAdaptor = require('../lib/frontend/rest-adaptor');
var Connection = require('../lib/backend/connection').Connection;

suite('REST API', function() {
  test('registeration of plugin commands', function() {
    var basePlugin = {
      getCommand: {
        method: 'GET',
        path: '/get',
        requestBuilder: function() {}
      },
      putCommand: {
        method: 'PUT',
        path: '/put',
        requestBuilder: function() {}
      },
      postCommand: {
        method: 'POST',
        path: '/post',
        requestBuilder: function() {}
      },
      deleteCommand: {
        method: 'DELETE',
        path: '/delete',
        requestBuilder: function() {}
      }
    };
    var overridingPlugin = {
      postCommand: {
        method: 'POST',
        path: '/post/overridden',
        requestBuilder: function() {}
      },
      deleteCommand: {
        method: 'DELETE',
        path: '/delete/overridden',
        requestBuilder: function() {}
      }
    };

    var application = express();
    var registeredCommands = restAdaptor.register(application, {
      prefix:     '',
      connection: utils.createStubbedBackendConnection(),
      plugins: [
        basePlugin,
        overridingPlugin
      ]
    });

    assert.deepEqual(registeredCommands,
                     [basePlugin.getCommand,
                      basePlugin.putCommand,
                      overridingPlugin.postCommand,
                      overridingPlugin.deleteCommand]);
  });

  suite('registeration', function() {
    function createHandlerFactory(type) {
      return function() {
        return function(request, response) {
          response.contentType('text/plain');
          response.send(type + ' OK', 200);
        };
      };
    }
    var handlersFactory = {
      search: createHandlerFactory('search')
    };

    var server;
    teardown(function() {
      if (server) {
        server.close();
      }
      server = undefined;
    });

    test('to the document root', function(done) {
      var fakeConnection = utils.createStubbedBackendConnection();
      var application = express();
      restAdaptor.register(application, {
        prefix:     '',
        connection: fakeConnection,
        handlers:   handlersFactory
      });
      utils.setupServer(application)
        .next(function(newServer) {
          server = newServer;
        })
        .get('/tables/foobar')
        .next(function(response) {
          assert.equal(response.body, 'search OK');
          done();
        })
        .error(function(error) {
          done(error);
        });
    });

    test('under specified path', function(done) {
      var fakeConnection = utils.createStubbedBackendConnection();
      var application = express();
      restAdaptor.register(application, {
        prefix:     '/path/to/kotoumi',
        connection: fakeConnection,
        handlers:   handlersFactory
      });
      utils.setupServer(application)
        .next(function(newServer) {
          server = newServer;
        })
        .get('/path/to/kotoumi/tables/foobar')
        .next(function(response) {
          assert.equal(response.body, 'search OK');
          done();
        })
        .error(function(error) {
          done(error);
        });
    });
  });

  test('creation of REST handler', function() {
    var requestBuilders = nodemock
          .mock('search')
            .takes({ request: true })
            .returns({ requestMessage: true });

    var onReceive = {};
    var connection = nodemock
          .mock('emitMessage')
            .takes('search', { requestMessage: true }, function() {}, {})
            .ctrl(2, onReceive);
    var handler = restAdaptor
          .createHandler({
            command:        'search',
            requestBuilder: requestBuilders.search,
            connection:     connection
          });

    var fakeRequest = { request: true };
    var fakeResponse = nodemock
          .mock('contentType')
            .takes('application/json')
          .mock('send')
            .takes({ response: true }, 200);

    handler(fakeRequest, fakeResponse);
    requestBuilders.assertThrows();
    connection.assertThrows();

    onReceive.trigger(null, { body: { response: true } });
    fakeResponse.assertThrows();
  });

  suite('default handlers', function() {
    var server;

    teardown(function() {
      if (server) {
        server.close();
      }
      server = undefined;
    });

    test('search', function(done) {
      var receiverCallback = {};
      var connection = {
            emitMessage: function(type, message, callback, options) {
              this.emitMessageCalledArguments.push({
                type:     type,
                message:  message,
                callback: callback,
                options:  options
              });
            },
            emitMessageCalledArguments: []
          };
      var application = express();
      restAdaptor.register(application, {
        prefix:     '',
        connection: connection
      });
      utils.setupServer(application)
        .next(function(newServer) {
          server = newServer;
          utils.get('/tables/foo?query=bar');
        })
        .wait(0.1)
        .next(function() {
          assert.equal(1, connection.emitMessageCalledArguments.length);
          var args = connection.emitMessageCalledArguments[0];
          assert.equal(args.type, 'search');

          var expected = {
            queries: {
              result: {
                source: 'foo',
                query:  'bar',
                output: utils.outputAll
              }
            }
          };
          assert.equalJSON(args.message, expected);

          done();
        })
        .error(function(error) {
          done(error);
        });
    });
  });
});


@@ -194,24 +194,93 @@
 -adaptor');%0A
+var restCommands = require('../lib/frontend/default-commands/rest');%0A
 var Connecti
@@ -1524,16 +1524,179 @@
        %5B
+%7B command: 'search',%0A                        definition: restCommands.search %7D,%0A                      %7B command: 'getCommand',%0A                        definition: 
 basePlug
@@ -1700,32 +1700,34 @@
 lugin.getCommand
+ %7D
 ,%0A              
@@ -1729,24 +1729,85 @@
             
+ %7B command: 'putCommand',%0A                        definition:
  basePlugin.
@@ -1808,32 +1808,34 @@
 lugin.putCommand
+ %7D
 ,%0A              
@@ -1833,32 +1833,94 @@
                 
+ %7B command: 'postCommand',%0A                        definition:
  overridingPlugi
@@ -1932,16 +1932,18 @@
 tCommand
+ %7D
 ,%0A      
@@ -1953,24 +1953,88 @@
             
+ %7B command: 'deleteCommand',%0A                        definition:
  overridingP
@@ -2052,16 +2052,18 @@
 eCommand
+ %7D
 %5D);%0A  %7D)

Update expected registerd commands