#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import
from __future__ import print_function

import unittest, os, json
from subprocess      import PIPE, STDOUT
from proton          import Message, Timeout
from system_test     import TestCase, Qdrouterd, main_module, DIR, TIMEOUT, Process
from proton.handlers import MessagingHandler
from proton.reactor  import Container, AtMostOnce, AtLeastOnce, DynamicNodeProperties, LinkOption, ApplicationEvent, EventInjector
from proton.utils    import BlockingConnection
from qpid_dispatch.management.client import Node

import time
import datetime

#====================================================
# Helper classes for all tests.
#====================================================


# Named timers allow test code to distinguish between several
# simultaneous timers, going off at different rates.
class Timeout ( object ):
    def __init__(self, parent, name):
        self.parent = parent
        self.name   = name

    def on_timer_task(self, event):
        self.parent.timeout ( self.name )



#================================================================
#     Setup
#================================================================

class TopologyAdditionTests ( TestCase ):

    @classmethod
    def setUpClass(cls):
        super(TopologyAdditionTests, cls).setUpClass()

        def router ( name, more_config ):

            config = [ ('router',  {'mode': 'interior', 'id': name}),
                       ('address', {'prefix': 'closest',   'distribution': 'closest'}),
                       ('address', {'prefix': 'balanced',  'distribution': 'balanced'}),
                       ('address', {'prefix': 'multicast', 'distribution': 'multicast'})
                     ]      \
                     + more_config

            config = Qdrouterd.Config(config)

            cls.routers.append(cls.tester.qdrouterd(name, config, wait=True))

        cls.routers = []

        client_ports = dict()
        client_ports['A'] = cls.tester.get_port()
        client_ports['B'] = cls.tester.get_port()
        client_ports['C'] = cls.tester.get_port()
        client_ports['D'] = cls.tester.get_port()

        cls.inter_router_ports = dict()
        cls.inter_router_ports['A'] = cls.tester.get_port()
        cls.inter_router_ports['B'] = cls.tester.get_port()

        initial_cost = 10
        lower_cost   =  8
        higher_cost  = 12

        # Only routers A and B are set up initially by this class.
        # Routers C and D are started by the test itself.
        router_A_config = [
                            ( 'listener',
                              { 'port': client_ports['A'],
                                'role': 'normal',
                                'stripAnnotations': 'no'
                              }
                            ),
                            ( 'listener',
                              {  'role': 'inter-router',
                                 'port': cls.inter_router_ports['A']
                              }
                            )
                         ]

        router_B_config = [
                            ( 'listener',
                              { 'port': client_ports['B'],
                                'role': 'normal',
                                'stripAnnotations': 'no'
                              }
                            ),
                            ( 'listener',
                              { 'role': 'inter-router',
                                'port': cls.inter_router_ports['B'],
                                'stripAnnotations': 'no'
                              }
                            ),
                            ( 'connector',
                              {  'name': 'AB_connector',
                                 'role': 'inter-router',
                                 'port': cls.inter_router_ports['A'],
                                 'cost':  initial_cost,
                                 'stripAnnotations': 'no'
                              }
                            )
                         ]

        router ( 'A', router_A_config )
        router ( 'B', router_B_config )

        router_A = cls.routers[0]
        router_B = cls.routers[1]

        router_A.wait_router_connected('B')

        cls.A_addr = router_A.addresses[0]
        cls.B_addr = router_B.addresses[0]



        # The two connections that this router will make, AC and BC,
        # will be lower cost than the direct AB route that the network
        # already has.
        cls.router_C_config = [
                                ( 'listener',
                                  { 'port': client_ports['C'],
                                    'role': 'normal',
                                    'stripAnnotations': 'no'
                                  }
                                ),
                                ( 'connector',
                                  {  'name': 'AC_connector',
                                     'role': 'inter-router',
                                     'port': cls.inter_router_ports['A'],
                                     'cost':  int(lower_cost / 2),
                                     'stripAnnotations': 'no',
                                     'linkCapacity' : 1000
                                  }
                                ),
                                ( 'connector',
                                  {  'name': 'BC_connector',
                                     'role': 'inter-router',
                                     'port': cls.inter_router_ports['B'],
                                     'cost':  int(lower_cost / 2),
                                     'stripAnnotations': 'no',
                                     'linkCapacity' : 1000
                                  }
                                )
                              ]

        # The two connections that this router will make, AD and BD,
        # will be higher cost than the other paths the networks already has
        # available to get from A to B.
        cls.router_D_config = [
                                ( 'listener',
                                  { 'port': client_ports['D'],
                                    'role': 'normal',
                                    'stripAnnotations': 'no'
                                  }
                                ),
                                ( 'connector',
                                  {  'name': 'AD_connector',
                                     'role': 'inter-router',
                                     'port': cls.inter_router_ports['A'],
                                     'cost':  int(higher_cost / 2),
                                     'stripAnnotations': 'no',
                                     'linkCapacity' : 1000
                                  }
                                ),
                                ( 'connector',
                                  {  'name': 'BD_connector',
                                     'role': 'inter-router',
                                     'port': cls.inter_router_ports['B'],
                                     'cost':  int(higher_cost / 2),
                                     'stripAnnotations': 'no',
                                     'linkCapacity' : 1000
                                  }
                                )
                              ]



    # This method allows test code to add new routers during the test,
    # rather than only at startup like A and B above.
    def addRouter ( self, name, more_config ) :
        config = [ ('router',  {'mode': 'interior', 'id': name}),
                   ('address', {'prefix': 'closest',   'distribution': 'closest'}),
                   ('address', {'prefix': 'balanced',  'distribution': 'balanced'}),
                   ('address', {'prefix': 'multicast', 'distribution': 'multicast'})
                 ]    \
                 + more_config

        config = Qdrouterd.Config(config)

        TopologyAdditionTests.routers.append(TopologyAdditionTests.tester.qdrouterd(name, config, wait=True))


    def test_01_new_route_low_cost ( self ):
        # During the test, test code will add a new router C,
        # connecting A and B with new low-cost links. At that
        # point the test's messages should switch from using
        # route AB to using route ACB.
        # By passing both of these routes to the test, I tell
        # it to expect both of them to be used.
        # If it terminates with the second path remaining unused
        # it will fail.
        #
        # Since this test alters the path that the messages follow,
        # it is OK for some messages to be released rather than
        # delivered. It doesn't always happen - depends on timing.
        initial_expected_trace = [ '0/A', '0/B' ]
        final_expected_trace   = [ '0/A', '0/C', '0/B' ]
        released_ok = True

        test = AddRouter ( self.A_addr,
                           self.B_addr,
                           "closest/01",
                           self,
                           'C',
                           self.router_C_config,
                           [ initial_expected_trace, final_expected_trace ],
                           released_ok
                         )
        test.run()
        self.assertEqual ( None, test.error )



    def test_02_new_route_high_cost ( self ):
        # During the test, test code will add a new router D,
        # connecting A and B with new links. But the links are
        # higher cost than what already exist. The network should
        # ignore them and keep using the lowest cost route that it
        # already has.
        # We communicate this expectation to the test by sending
        # it a single expected trace. The test will fail with
        # error if any other traces are encountered.
        #
        # Since this test does not alter the path that the messages
        # follow, it is *not* OK for any messages to be released
        # rather than delivered.
        only_expected_trace   = [ '0/A', '0/C', '0/B' ]
        released_ok = False

        test = AddRouter ( self.A_addr,
                           self.B_addr,
                           "closest/02",
                           self,
                           'D',
                           self.router_D_config,
                           [ only_expected_trace ],
                           released_ok
                         )
        test.run()
        self.assertEqual ( None, test.error )




#================================================================
#     Tests
#================================================================


#--------------------------------------------------------------
#
# First test
# ------------------
#
# Send some messages through the original A---B router network,
# Then change it to look like this:
#
#                    C
#                   / \
#                  /   \
#                 /     \
#                /       \
#               A -------- B
#
# But the caller controls what costs are assigned to the two
# new links, so only the caller knows whether messages should
# start to flow through the new route ACB or not. It passes
# that knowledge in to us as a list of expected paths.
# This test's job is to make sure that all the expected paths
# get used by messages, and no others get used.
#
#
# Second test
# ------------------
#
# The triangular network from the first test still exists, and
# we will add to it a new router D which also connects A and B.
#
#                    C
#                   / \
#                  /   \
#                 /     \
#                /       \
#               A -------- B
#                \       /
#                 \     /
#                  \   /
#                   \ /
#                    D
# As in the first test, the caller tells us what routes ought
# to be followed, by putting them in the 'expected_traces' arg.
#
#--------------------------------------------------------------

class AddRouter ( MessagingHandler ):
    def __init__ ( self,
                   send_addr,
                   recv_addr,
                   destination,
                   parent,
                   new_router_name,
                   new_router_config,
                   expected_traces,
                   released_ok
                 ):
        super(AddRouter, self).__init__(prefetch=100)
        self.send_addr         = send_addr
        self.recv_addr         = recv_addr
        self.dest              = destination
        self.parent            = parent
        self.new_router_name   = new_router_name
        self.new_router_config = new_router_config
        self.released_ok       = released_ok

        self.error         = None
        self.sender        = None
        self.receiver      = None

        self.n_messages    = 30
        self.n_sent        = 0
        self.n_received    = 0
        self.n_released    = 0
        self.n_accepted    = 0

        self.test_timer    = None
        self.send_timer    = None
        self.timeout_count = 0
        self.reactor       = None
        self.container     = None
        self.finishing     = False

        # The parent sends us a list of the traces we
        # ought to see on messages.
        # Make a little data structure that
        # will keep track of how many times each trace was seen.
        self.expected_trace_counts = list()
        for i in range ( len(expected_traces )) :
            self.expected_trace_counts.append ( [ expected_traces[i], 0 ] )


    def run ( self ) :
        Container(self).run()


    # Close everything and allow the test to terminate.
    def bail ( self, reason_for_bailing ) :
        self.finishing = True
        self.error = reason_for_bailing
        self.receiver.close()
        self.send_conn.close()
        self.recv_conn.close()
        self.test_timer.cancel()
        self.send_timer.cancel()


    # There are two timers. The 'test' timer should only expire if
    # something has gone wrong, in which case it terminates the test.
    # The 'send' timer expires frequently, and every time it goes off
    # we send out a little batch of messages.
    def timeout ( self, name ):

        if self.finishing :
            return

        self.timeout_count += 1
        if name == "test" :
            self.bail ( "Timeout Expired: %d messages received, %d expected." % (self.n_received, self.n_messages) )
        elif name == "send" :
            self.send()
            self.send_timer = self.reactor.schedule(1, Timeout(self, "send"))

            # At T+5, create the new router with link costs as
            # specified by parent. We do it partway into the test
            # so that some messages will flow through the original
            # network, and some will flow through the network with
            # the new router added.
            if self.timeout_count == 5 :
                self.parent.addRouter ( self.new_router_name, self.new_router_config )


    def on_start(self, event):
        self.reactor   = event.reactor
        self.container = event.container

        self.test_timer  = self.reactor.schedule(TIMEOUT, Timeout(self, "test"))
        self.send_timer  = self.reactor.schedule(1, Timeout(self, "send"))

        self.send_conn   = event.container.connect(self.send_addr)
        self.recv_conn   = event.container.connect(self.recv_addr)

        self.sender      = event.container.create_sender(self.send_conn, self.dest)
        self.receiver    = event.container.create_receiver(self.recv_conn, self.dest)
        self.receiver.flow ( self.n_messages )


    #------------------------------------------------------------
    # Sender Side
    #------------------------------------------------------------

    def send(self):

        if self.n_sent >= self.n_messages :
            return

        # Send little bursts of 3 messages every sender-timeout.
        for _ in range(3) :
            msg = Message(body=self.n_sent)
            self.sender.send(msg)
            self.n_sent += 1
            if self.n_sent == self.n_messages :
                return


    # The caller of this tests decides whether it is OK or
    # not OK to have some messages released during the test.
    def on_released ( self, event ) :
        if self.released_ok :
            self.n_released += 1
            self.check_count ( )
        else :
            self.bail ( "a message was released." )


    def on_accepted ( self, event ) :
        self.n_accepted += 1
        self.check_count ( )


    #
    # Do the released plus the accepted messages add up to the number
    # that were sent? If so, bail out with success.
    # Do NOT end the test if the number is still shy of the expected
    # total. The callers of this method just call it every time they
    # get something -- it will be called many times poer test.
    #
    # Pleae Note:
    #   This check is on the 'sender' side of this test, rather than the
    #   'receiver' side, because it is to the sender that we make a
    #   guarantee: namely, that the sender should know the disposition of
    #   all sent messages -- whether they have been accepted by the receiver,
    #   or released by the router network.
    #
    def check_count ( self ) :
        if self.n_accepted + self.n_released == self.n_messages :
            self.finishing = True
            self.finish_test ( )



    #------------------------------------------------------------
    # Receiver Side
    #------------------------------------------------------------

    def on_message(self, event):
        if self.finishing :
            return
        self.n_received += 1
        trace = event.message.annotations [ 'x-opt-qd.trace' ]
        # Introduce flaws for debugging.
        # if self.n_received == 13 :
        #     trace = [ '0/B', '0/A', '0/D' ]
        # if self.n_received == 13 :
        #     self.n_received -= 1
        self.record_trace ( trace )
        self.check_count ( )


    # Compare the trace that came from a message to the list of
    # traces the caller told us to expect. If it is one of the
    # expected traces, count it. Otherwise, fail the test.
    def record_trace ( self, observed_trace ):
        for trace_record in self.expected_trace_counts :
            trace = trace_record [ 0 ]
            if observed_trace == trace :
                trace_record [ 1 ] += 1
                return
        # If we get here, the trace is one we were not expecting. That's bad.
        self.bail ( "Unexpected trace: %s" % observed_trace )


    # Shut down everything and make sure that all of the extected traces
    # have been seen.
    def finish_test ( self ) :
        self.test_timer.cancel()
        self.send_timer.cancel()
        for trace_record in self.expected_trace_counts :
            count = trace_record[1]
            # Deliberate flaw for debugging.
            # count = 0
            if count <= 0 :
                self.bail ( "Trace %s was not seen." % trace_record[0] )
                return

        # success
        self.bail ( None )



if __name__ == '__main__':
    unittest.main(main_module())
