/* global describe, it, xit, before, beforeEach, after, afterEach */
/* jslint node: true, esnext: true */

"use strict";

const chai = require('chai'),
  assert = chai.assert,
  expect = chai.expect,
  should = chai.should(),
  Service = require('../lib/Service'),
  ServiceConfig = require('../lib/ServiceConfig'),
  ServiceLogger = require('../lib/ServiceLogger'),
  ServiceProviderMixin = require('../lib/ServiceProviderMixin');

class ServiceProvider extends ServiceProviderMixin(Service) {}

class ServiceTest extends Service {
  static get name() {
    return "test";
  }
  get type() {
    return ServiceTest.name;
  }

  get autostart() {
    return true;
  }

  configure(config) {
    delete config.name;
    Object.assign(this, config);
    return this.restartIfRunning();
  }
}

describe('service provider', () => {
  const sp = new ServiceProvider([{
    name: 'a'
  }, {
    name: 'test',
    key3: 3
  }]);

  describe('initial setup', () => {
    describe('config service', () => {
      it('present', () => assert.equal(sp.services.config.name, 'config'));
      it('preserved initial config', () => assert.deepEqual(Object.keys(sp.services.config.preservedConfigs), [
        'a', 'test'
      ]));
    });

    it('logger service', () => assert.equal(sp.services.logger.name, 'logger'));
    it('can be started', () => sp.start().then(() => assert.equal(sp.state, 'running')));
    it('service provider service', () => assert.equal(sp.services.a.name, 'a'));
  });

  describe('without initial config', () => {
    const sp = new ServiceProvider();
    it('present', () => assert.equal(sp.services.config.name, 'config'));
  });

  describe('logging', () => {
    // TODO wait until logger service has fullfilled
    sp.info(`logging`);
  });

  describe('additional service', () => {
    sp.registerService(new ServiceTest({}, sp));
    sp.registerService(new ServiceTest({
      name: "t2"
    }, sp));

    it('test service', () => assert.equal(sp.services.test.name, 'test'));

    describe('configure service', () => {
      it('direct', () => sp.services.test.configure({
        key: "new value"
      }).then(() =>
        assert.equal(sp.services.test.key, "new value")
      ));

      it('send change request over config service', () =>
        sp.services.config.endpoints.config.receive([{
          name: 'config'
        }, {
          name: 'unknown'
        }, {
          name: 'test',
          key1: 4711,
          key2: "2"
        }]).then(() =>
          assert.equal(sp.services.test.key1, 4711)
        )
      );
    });

    it('can be unregistered', () =>
      sp.unregisterService('t2').then(s => assert.isUndefined(sp.services.t2))
    );
  });

  describe('declare service', () => {
    describe('with type', () => {
      setTimeout(() =>
        sp.registerServiceFactory(ServiceTest), 50);

      // force pending promises
      sp.declareService({
        name: 's2',
        type: 'test'
      }, true);
      sp.declareService({
        name: 's2',
        type: 'test'
      }, true);

      it('can be declared', () =>
        sp.declareService({
          name: 's2',
          type: 'test',
          key: 1
        }, true).then(
          s => {
            assert.equal(s.name, "s2");
          }
        )
      );

      it('can be declared again', () =>
        sp.declareService({
          name: 's2',
          type: 'test',
          key: 2
        }, true).then(
          s => {
            assert.equal(s.name, "s2");
            assert.equal(s.key, 2);
          }
        )
      );
    });

    describe('without type', () => {
      const sp = new ServiceProvider([{}, {
        name: 'test',
        value: 77
      }]);

      sp.declareService({
        name: 'test'
      }, true);

      setTimeout(() =>
        sp.registerServiceFactory(ServiceTest), 50);

      it('can be declared', () =>
        sp.declareService({
          name: 'test'
        }, true).then(
          s => {
            assert.equal(s.name, "test");
            //assert.equal(s.value, 77);
          }
        )
      );
    });
  });
});

@@ -220,16 +220,57 @@
 ould(),%0A
+  endpoint = require('kronos-endpoint'),%0A
   Servic
@@ -296,24 +296,24 @@
 /Service'),%0A
-
   ServiceCon
@@ -1790,32 +1790,374 @@
 gging%60);%0A  %7D);%0A%0A
+  describe('command endpoint', () =%3E %7B%0A    const testEndpoint = new endpoint.SendEndpoint('test');%0A    testEndpoint.connected = sp.endpoints.command;%0A%0A    it('info ', () =%3E %7B%0A      testEndpoint.receive(%7B%0A        data: %7B%0A          action: %22list%22%0A        %7D%0A      %7D).then(r =%3E %7B%0A        assert.deepEqual(r, %5B'config'%5D);%0A      %7D);%0A    %7D);%0A  %7D);%0A%0A
   describe('addi
@@ -3397,32 +3397,32 @@
    type: 'test'%0A
+
       %7D, true);%0A
@@ -3417,25 +3417,24 @@
   %7D, true);%0A
-%0A
       it('ca

command endpoint