// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var collectParallel = require('collect-parallel/array');
var allocCluster = require('../lib/test-cluster.js');

allocCluster.test('find connections for service', {
    size: 10,
    dummySize: 5
}, function t(cluster, assert) {
    var apps = cluster.apps;
    var dummies = cluster.dummies;
    var entryNode = apps[0];

    setup();

    function setup() {
        assert.comment('-- setup');

        collectParallel(
            dummies,
            function registerEach(dummy, i, done) {
                cluster.sendRegister(dummy, {
                    serviceName: 'Dummy'
                }, done);
            },
            function finishRegister(_, results) {
                for (var i = 0; i < results.length; i++) {
                    var res = results[i];
                    assert.ifError(res.err, 'no unexpected error from register ' + i);
                }
                runTest();
            }
        );
    }

    function runTest() {
        assert.comment('-- runTest');

        pruneClusterPears(cluster, assert, runTestPruneDone);
    }

    function runTestPruneDone() {
        assert.comment('-- runTestPruneDone');

        cluster.checkExitPeers(assert, {
            serviceName: 'Dummy',
            hostPort: dummies[0].hostPort
        });

        entryNode.client.getConnections({
            serviceName: 'Dummy'
        }, onResults);
    }

    function onResults(err, resp) {
        assert.comment('-- onResults');

        if (err) {
            finish(err);
            return;
        }

        var exitHosts = entryNode.hostsFor('Dummy');

        var body = resp.body;
        assert.deepEqual(
            exitHosts.sort(),
            Object.keys(body).sort(),
            'got expected exit hosts back');

        Object.keys(body).forEach(function checkInstances(key) {
            if (body[key].err) {
                assert.ifError(body[key].err);
                return;
            }

            var exitInstances = body[key].instances;

            Object.keys(exitInstances).forEach(function checkInst(key2) {
                var exitInstance = exitInstances[key2];

                var isConnected = exitInstance.connected.out ||
                    exitInstance.connected.in;

                assert.equal(isConnected, true,
                    'exit instance is connected');
            });
        });

        finish(null);
    }

    function finish(err) {
        assert.comment('-- finish');
        assert.ifError(err);

        assert.end();
    }
});

function pruneClusterPears(cluster, assert, callback) {
    collectParallel(
        cluster.apps,
        function pruneEach(app, i, done) {
            var serviceProxy = app.clients.serviceProxy;
            serviceProxy.peerPruner.run(done);
        },
        function finish(_, results) {
            for (var i = 0; i < results.length; i++) {
                var res = results[i];
                assert.ifError(res.err, 'no error from pruning app ' + i);
            }
            callback();
        }
    );
}

@@ -3130,17 +3130,17 @@
 tances;%0A
-%0A
+ 
         
@@ -3134,32 +3134,50 @@
 es;%0A            
+var areConnected =
  Object.keys(exi
@@ -3188,23 +3188,19 @@
 tances).
-forEach
+map
 (functio
@@ -3201,25 +3201,36 @@
 unction 
-checkInst
+getInstanceConnected
 (key2) %7B
@@ -3286,17 +3286,16 @@
 %5Bkey2%5D;%0A
-%0A
         
@@ -3306,25 +3306,14 @@
     
-var isConnected =
+return
  exi
@@ -3355,24 +3355,27 @@
             
+   
 exitInstance
@@ -3389,24 +3389,33 @@
 ted.in;%0A
-%0A
+     
        
+%7D);%0A%0A
         
@@ -3419,23 +3419,24 @@
     
+   
 assert.
-equal(is
+ok(are
 Conn
@@ -3444,14 +3444,23 @@
 cted
-, true
+.every(boolEye)
 ,%0A  
@@ -3477,17 +3477,23 @@
         
-'
+  'all 
 exit ins
@@ -3497,19 +3497,21 @@
 instance
- is
+s are
  connect
@@ -3516,32 +3516,16 @@
 cted');%0A
-            %7D);%0A
         
@@ -4205,8 +4205,49 @@
    );%0A%7D%0A
+%0Afunction boolEye(x) %7B%0A    return !!x;%0A%7D%0A

refactor the all connected check