// 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 Statsd = require('uber-statsd-client');
var parseArgs = require('minimist');
var process = require('process');
var assert = require('assert');

var TChannel = require('../channel.js');
var ServiceProxy = require('../hyperbahn/service_proxy.js');
var FakeEgressNodes = require('../test/lib/fake-egress-nodes.js');

var argv = parseArgs(process.argv.slice(2), {
    boolean: ['trace']
});

if (argv.type === 'bench-relay') {
    process.title = 'nodejs-benchmarks-relay_bench_server';
} else if (argv.type === 'trace-relay') {
    process.title = 'nodejs-benchmarks-relay_trace_server';
}

RelayServer(argv);

function RelayServer(opts) {
    /*eslint max-statements: [2, 25]*/
    if (!(this instanceof RelayServer)) {
        return new RelayServer(opts);
    }

    var self = this;

    assert(opts.benchPort, 'benchPort required');
    assert(opts.benchRelayPort, 'benchRelayPort required');
    assert(opts.tracePort, 'tracePort required');
    assert(opts.traceRelayPort, 'traceRelayPort required');
    assert(
        opts.type === 'bench-relay' || opts.type === 'trace-relay',
        'a valid type required'
    );
    assert('trace' in opts, 'trace is a required options');
    assert('debug' in opts, 'debug is a required options');

    var benchRelayHostPort = '127.0.0.1:' + opts.benchRelayPort;
    var traceRelayHostPort = '127.0.0.1:' + opts.traceRelayPort;

    self.relay = TChannel({
        statTags: {
            app: 'relay-server'
        },
        logger: opts.debug ? require('debug-logtron')('relay') : null,
        trace: false,
        statsd: new Statsd({
            host: '127.0.0.1',
            port: 7036
        })
    });
    self.relay.handler = ServiceProxy({
        channel: self.relay,
        egressNodes: FakeEgressNodes({
            hostPort: opts.type === 'bench-relay' ?
                benchRelayHostPort : opts.type === 'trace-relay' ?
                traceRelayHostPort : null,
            topology: {
                'benchmark': [benchRelayHostPort],
                'tcollector': [traceRelayHostPort]
            }
        })
    });

    self.serviceName = opts.type === 'bench-relay' ? 'benchmark' :
        opts.type === 'trace-relay' ? 'tcollector' :
        'unknown';
    self.port = opts.type === 'bench-relay' ? opts.benchRelayPort :
        opts.type === 'trace-relay' ? opts.traceRelayPort :
        null;
    self.targetPort = opts.type === 'bench-relay' ? opts.benchPort :
        opts.type === 'trace-relay' ? opts.tracePort :
        null;

    self.type = opts.type;

    self.relay.handler.createServiceChannel(self.serviceName);
    self.relay.listen(self.port, '127.0.0.1', onListen);

    function onListen() {
        self.connect();
    }
}

RelayServer.prototype.connect = function connect() {
    var self = this;

    var basePort = parseInt(self.targetPort, 10);
    var targetHostPort = '127.0.0.1:' + basePort;

    var peer = self.relay.handler.getServicePeer(
        self.serviceName, targetHostPort
    );
    peer.connect();
};

@@ -3670,16 +3670,53 @@
 ts.type;
+%0A    self.instances = opts.instances;
 %0A%0A    se
@@ -4014,16 +4014,68 @@
 t, 10);%0A
+%0A    for (var i = 0; i %3C self.instances; i++) %7B%0A    
     var 
@@ -4106,24 +4106,25 @@
 0.1:' + 
+(
 basePort
 ;%0A%0A    v
@@ -4115,23 +4115,32 @@
 basePort
+ + i)
 ;%0A%0A    
+  
+  
 var peer
@@ -4181,24 +4181,28 @@
 er(%0A        
+    
 self.service
@@ -4222,23 +4222,31 @@
 ostPort%0A
+    
     );%0A
+    
     peer
@@ -4257,11 +4257,17 @@
 nect();%0A
+    %7D%0A
 %7D;%0A

make relay use N instances like prod