"""
Copyright 2016 Open Networking Foundation (ONF)

Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>

    TestON is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    TestON is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with TestON.  If not, see <http://www.gnu.org/licenses/>.
"""

"""
This file contains classes for CHOTestMonkey that are related to application event
Author: you@onlab.us
"""
from tests.CHOTestMonkey.dependencies.events.Event import EventType, EventStates, Event
from tests.CHOTestMonkey.dependencies.elements.ONOSElement import HostIntent, PointIntent


class IntentEvent( Event ):

    def __init__( self ):
        Event.__init__( self )
        # The index of the ONOS CLI that is going to run the command
        self.CLIIndex = 0

    def getRandomCorrespondent( self, hostA, connected=True ):
        import random
        if connected:
            candidates = hostA.correspondents
        else:
            candidates = [ host for host in main.hosts if host not in hostA.correspondents and host != hostA ]
        if len( candidates ) == 0:
            return None
        hostB = random.sample( candidates, 1 )[ 0 ]
        return hostB

    def getRandomHostPair( self, connected=True ):
        import random
        candidateDict = {}
        with main.variableLock:
            for host in main.hosts:
                correspondent = self.getRandomCorrespondent( host, connected=connected )
                if correspondent is not None:
                    candidateDict[ host ] = correspondent
            if candidateDict == {}:
                return None
            hostA = random.sample( candidateDict.keys(), 1 )[ 0 ]
            hostB = candidateDict[ hostA ]
            return [ hostA, hostB ]

    def getIntentsByType( self, intentType ):
        intents = []
        with main.variableLock:
            for intent in main.intents:
                if intent.type == intentType:
                    intents.append( intent )
        return intents

    def getRandomIntentByType( self, intentType ):
        import random
        intents = self.getIntentsByType( intentType )
        if len( intents ) == 0:
            return None
        intent = random.sample( intents, 1 )[ 0 ]
        return intent


class HostIntentEvent( IntentEvent ):

    def __init__( self ):
        IntentEvent.__init__( self )
        self.hostA = None
        self.hostB = None

    def startHostIntentEvent( self ):
        return EventStates().PASS

    def startEvent( self, args ):
        with self.eventLock:
            #main.log.info( "%s - starting event" % ( self.typeString ) )
            if self.typeIndex == EventType().APP_INTENT_HOST_ADD or self.typeIndex == EventType().APP_INTENT_HOST_DEL:
                if len( args ) < 3:
                    main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
                    return EventStates().ABORT
                elif len( args ) > 3:
                    main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
                    return EventStates().ABORT
                try:
                    if args[ 0 ] == 'random' or args[ 1 ] == 'random':
                        if self.typeIndex == EventType().APP_INTENT_HOST_ADD:
                            hostPairRandom = self.getRandomHostPair( connected=False )
                            if hostPairRandom is None:
                                main.log.warn( "All host pairs are connected, aborting event" )
                                return EventStates().ABORT
                            self.hostA = hostPairRandom[ 0 ]
                            self.hostB = hostPairRandom[ 1 ]
                        elif self.typeIndex == EventType().APP_INTENT_HOST_DEL:
                            intent = self.getRandomIntentByType( 'INTENT_HOST' )
                            if intent is None:
                                main.log.warn( "No host intent for deletion, aborting event" )
                                return EventStates().ABORT
                            self.hostA = intent.hostA
                            self.hostB = intent.hostB
                    elif args[ 0 ] == args[ 1 ]:
                        main.log.warn( "%s - invalid argument: %s, %s" % ( self.typeString, args[ 0 ], args[ 1 ] ) )
                        return EventStates().ABORT
                    else:
                        for host in main.hosts:
                            if host.name == args[ 0 ]:
                                self.hostA = host
                            elif host.name == args[ 1 ]:
                                self.hostB = host
                            if self.hostA is not None and self.hostB is not None:
                                break
                        if self.hostA is None:
                            main.log.warn( "Host %s does not exist: " % ( args[ 0 ] ) )
                            return EventStates().ABORT
                        if self.hostB is None:
                            main.log.warn( "Host %s does not exist: " % ( args[ 1 ] ) )
                            return EventStates().ABORT
                    index = int( args[ 2 ] )
                    if index < 1 or index > int( main.Cluster.numCtrls ):
                        main.log.warn( "%s - invalid argument: %s" % ( self.typeString, index ) )
                        return EventStates().ABORT
                    if not main.controllers[ index - 1 ].isUp():
                        main.log.warn( self.typeString + " - invalid argument: onos %s is down" % ( controller.index ) )
                        return EventStates().ABORT
                    self.CLIIndex = index
                    return self.startHostIntentEvent()
                except Exception:
                    main.log.warn( "Caught exception, aborting event" )
                    return EventStates().ABORT


class AddHostIntent( HostIntentEvent ):

    """
    Add a host-to-host intent ( bidirectional )
    """
    def __init__( self ):
        HostIntentEvent.__init__( self )
        self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
        self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )

    def startHostIntentEvent( self ):
        try:
            assert self.hostA is not None and self.hostB is not None
            # Check whether there already exists some intent for the host pair
            # For now we should avoid installing overlapping intents
            for intent in main.intents:
                if not intent.type == 'INTENT_HOST':
                    continue
                if intent.hostA == self.hostA and intent.hostB == self.hostB or\
                        intent.hostB == self.hostA and intent.hostA == self.hostB:
                    main.log.warn( self.typeString + " - find an exiting intent for the host pair, abort installation" )
                    return EventStates().ABORT
            main.log.info( "Event recorded: {} {} {} {} {}".format( self.typeIndex, self.typeString, self.hostA.name, self.hostB.name, self.CLIIndex ) )
            controller = main.controllers[ self.CLIIndex - 1 ]
            with controller.CLILock:
                id = controller.CLI.addHostIntent( self.hostA.id, self.hostB.id )
            if id is None:
                main.log.warn( self.typeString + " - add host intent failed" )
                return EventStates().FAIL
            with main.variableLock:
                newHostIntent = HostIntent( id, self.hostA, self.hostB )
                if self.hostA.isDown() or self.hostA.isRemoved() or self.hostB.isDown() or self.hostB.isRemoved():
                    newHostIntent.setFailed()
                else:
                    newHostIntent.setInstalled()
                main.intents.append( newHostIntent )
            return EventStates().PASS
        except Exception:
            main.log.warn( "Caught exception, aborting event" )
            return EventStates().ABORT


class DelHostIntent( HostIntentEvent ):

    """
    Delete a host-to-host intent ( bidirectional )
    """
    def __init__( self ):
        HostIntentEvent.__init__( self )
        self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
        self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )

    def startHostIntentEvent( self ):
        try:
            assert self.hostA is not None and self.hostB is not None
            targetIntent = None
            for intent in main.intents:
                if not intent.type == 'INTENT_HOST':
                    continue
                if intent.hostA == self.hostA and intent.hostB == self.hostB or\
                        intent.hostB == self.hostA and intent.hostA == self.hostB:
                    targetIntent = intent
                    break
            if targetIntent is None:
                main.log.warn( self.typeString + " - intent does not exist" )
                return EventStates().FAIL
            main.log.info( "Event recorded: {} {} {} {} {}".format( self.typeIndex, self.typeString, self.hostA.name, self.hostB.name, self.CLIIndex ) )
            controller = main.controllers[ self.CLIIndex - 1 ]
            with controller.CLILock:
                result = controller.CLI.removeIntent( targetIntent.id, purge=True )
            if result is None or result == main.FALSE:
                main.log.warn( self.typeString + " - delete host intent failed" )
                return EventStates().FAIL
            with main.variableLock:
                targetIntent.setWithdrawn()
                main.intents.remove( targetIntent )
            return EventStates().PASS
        except Exception:
            main.log.warn( "Caught exception, aborting event" )
            return EventStates().ABORT


class PointIntentEvent( IntentEvent ):

    def __init__( self ):
        IntentEvent.__init__( self )
        self.deviceA = None
        self.deviceB = None

    def startPointIntentEvent( self ):
        return EventStates().PASS

    def startEvent( self, args ):
        with self.eventLock:
            #main.log.info( "%s - starting event" % ( self.typeString ) )
            if self.typeIndex == EventType().APP_INTENT_POINT_ADD or self.typeIndex == EventType().APP_INTENT_POINT_DEL:
                if len( args ) < 3:
                    main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
                    return EventStates().ABORT
                elif len( args ) > 4:
                    main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
                    return EventStates().ABORT
                try:
                    if args[ 0 ] == 'random' or args[ 1 ] == 'random':
                        if self.typeIndex == EventType().APP_INTENT_POINT_ADD:
                            hostPairRandom = self.getRandomHostPair( connected=False )
                            if hostPairRandom is None:
                                main.log.warn( "All host pairs are connected, aborting event" )
                                return EventStates().ABORT
                            self.deviceA = hostPairRandom[ 0 ].device
                            self.deviceB = hostPairRandom[ 1 ].device
                        elif self.typeIndex == EventType().APP_INTENT_POINT_DEL:
                            intent = self.getRandomIntentByType( 'INTENT_POINT' )
                            if intent is None:
                                main.log.warn( "No point intent for deletion, aborting event" )
                                return EventStates().ABORT
                            self.deviceA = intent.deviceA
                            self.deviceB = intent.deviceB
                    elif args[ 0 ] == args[ 1 ]:
                        main.log.warn( "%s - invalid argument: %s" % ( self.typeString, args[ 0 ], args[ 1 ] ) )
                        return EventStates().ABORT
                    else:
                        for device in main.devices:
                            if device.name == args[ 0 ]:
                                self.deviceA = device
                            elif device.name == args[ 1 ]:
                                self.deviceB = device
                            if self.deviceA is not None and self.deviceB is not None:
                                break
                        if self.deviceA is None:
                            main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
                            return EventStates().ABORT
                        if self.deviceB is None:
                            main.log.warn( "Device %s does not exist: " % ( args[ 1 ] ) )
                            return EventStates().ABORT
                    index = int( args[ 2 ] )
                    if index < 1 or index > int( main.Cluster.numCtrls ):
                        main.log.warn( "%s - invalid argument: %s" % ( self.typeString, index ) )
                        return EventStates().ABORT
                    if not main.controllers[ index - 1 ].isUp():
                        main.log.warn( self.typeString + " - invalid argument: onos %s is down" % ( controller.index ) )
                        return EventStates().ABORT
                    self.CLIIndex = index
                    if len( args ) == 4 and args[ 3 ] == 'bidirectional':
                        # Install point intents for both directions
                        resultA = self.startPointIntentEvent()
                        [ self.deviceA, self.deviceB ] = [ self.deviceB, self.deviceA ]
                        resultB = self.startPointIntentEvent()
                        if resultA == EventStates().PASS and resultB == EventStates().PASS:
                            return EventStates().PASS
                        else:
                            return EventStates().FAIL
                    else:
                        return self.startPointIntentEvent()
                except Exception:
                    main.log.warn( "Caught exception, aborting event" )
                    return EventStates().ABORT


class AddPointIntent( PointIntentEvent ):

    """
    Add a point-to-point intent
    """
    def __init__( self ):
        PointIntentEvent.__init__( self )
        self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
        self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )

    def startPointIntentEvent( self ):
        try:
            assert self.deviceA is not None and self.deviceB is not None
            controller = main.controllers[ self.CLIIndex - 1 ]
            # TODO: support multiple hosts under one device
            # Check whether there already exists some intent for the device pair
            # For now we should avoid installing overlapping intents
            for intent in main.intents:
                if not intent.type == 'INTENT_POINT':
                    continue
                if intent.deviceA == self.deviceA and intent.deviceB == self.deviceB:
                    main.log.warn( self.typeString + " - find an exiting intent for the device pair, abort installation" )
                    return EventStates().ABORT
            main.log.info( "Event recorded: {} {} {} {} {}".format( self.typeIndex, self.typeString, self.deviceA.name, self.deviceB.name, self.CLIIndex ) )
            controller = main.controllers[ self.CLIIndex - 1 ]
            with controller.CLILock:
                srcMAC = ""
                dstMAC = ""
                if len( self.deviceA.hosts ) > 0:
                    srcMAC = self.deviceA.hosts[ 0 ].mac
                if len( self.deviceB.hosts ) > 0:
                    dstMAC = self.deviceB.hosts[ 0 ].mac
                id = controller.CLI.addPointIntent( self.deviceA.dpid, self.deviceB.dpid, 1, 1, '', srcMAC, dstMAC )
            if id is None:
                main.log.warn( self.typeString + " - add point intent failed" )
                return EventStates().FAIL
            with main.variableLock:
                newPointIntent = PointIntent( id, self.deviceA, self.deviceB )
                if self.deviceA.isDown() or self.deviceB.isDown() or self.deviceA.isRemoved() or self.deviceB.isRemoved():
                    newPointIntent.setFailed()
                else:
                    newPointIntent.setInstalled()
                main.intents.append( newPointIntent )
            return EventStates().PASS
        except Exception:
            main.log.warn( "Caught exception, aborting event" )
            return EventStates().ABORT


class DelPointIntent( PointIntentEvent ):

    """
    Delete a point-to-point intent
    """
    def __init__( self ):
        PointIntentEvent.__init__( self )
        self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
        self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )

    def startPointIntentEvent( self ):
        try:
            assert self.deviceA is not None and self.deviceB is not None
            targetIntent = None
            for intent in main.intents:
                if not intent.type == 'INTENT_POINT':
                    continue
                if intent.deviceA == self.deviceA and intent.deviceB == self.deviceB:
                    targetIntent = intent
                    break
            if targetIntent is None:
                main.log.warn( self.typeString + " - intent does not exist" )
                return EventStates().FAIL
            main.log.info( "Event recorded: {} {} {} {} {}".format( self.typeIndex, self.typeString, self.deviceA.name, self.deviceB.name, self.CLIIndex ) )
            controller = main.controllers[ self.CLIIndex - 1 ]
            with controller.CLILock:
                result = controller.CLI.removeIntent( targetIntent.id, purge=True )
            if result is None or result == main.FALSE:
                main.log.warn( self.typeString + " - delete point intent failed" )
                return EventStates().FAIL
            with main.variableLock:
                targetIntent.setWithdrawn()
                main.intents.remove( targetIntent )
            return EventStates().PASS
        except Exception:
            main.log.warn( "Caught exception, aborting event" )
            return EventStates().ABORT
