/*
 * Copyright 2017-present Open Networking Laboratory
 *
 * Licensed 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.
 */

package org.onosproject.routing.cpr;

import com.google.common.collect.Sets;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.app.ApplicationService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceEvent;
import org.onosproject.incubator.net.intf.InterfaceListener;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.incubator.net.intf.InterfaceServiceAdapter;
import org.onosproject.mastership.MastershipService;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigEvent.Type;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.routing.RoutingService;
import org.onosproject.routing.config.RouterConfig;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
import static org.onosproject.routing.cpr.ControlPlaneRedirectManager.ACL_PRIORITY;
import static org.onosproject.routing.cpr.ControlPlaneRedirectManager.buildArpSelector;
import static org.onosproject.routing.cpr.ControlPlaneRedirectManager.buildIPDstSelector;
import static org.onosproject.routing.cpr.ControlPlaneRedirectManager.buildIPSrcSelector;
import static org.onosproject.routing.cpr.ControlPlaneRedirectManager.buildNdpSelector;

/**
 * UnitTests for ControlPlaneRedirectManager.
 */
@Ignore("Too many dependencies on internal implementation, too hard to maintain")
public class ControlPlaneRedirectManagerTest {

    private DeviceService deviceService;
    private FlowObjectiveService flowObjectiveService;
    private NetworkConfigService networkConfigService;
    private final Set<Interface> interfaces = Sets.newHashSet();
    static Device dev3 = NetTestTools.device("0000000000000001");
    private static final int OSPF_IP_PROTO = 0x59;
    private CoreService coreService = new TestCoreService();
    private InterfaceService interfaceService;
    private static final ApplicationId APPID = TestApplicationId.create("org.onosproject.vrouter");

    private static final DeviceId DEVICE_ID = DeviceId.deviceId("of:0000000000000001");

    private ConnectPoint controlPlaneConnectPoint = new ConnectPoint(DEVICE_ID,
            PortNumber.portNumber(1));

    private static final ConnectPoint SW1_ETH1 = new ConnectPoint(DEVICE_ID,
            PortNumber.portNumber(1));

    private static final ConnectPoint SW1_ETH2 = new ConnectPoint(DEVICE_ID,
            PortNumber.portNumber(2));

    private static final ConnectPoint SW1_ETH3 = new ConnectPoint(DEVICE_ID,
            PortNumber.portNumber(3));

    private ControlPlaneRedirectManager controlPlaneRedirectManager = new ControlPlaneRedirectManager();
    private RouterConfig routerConfig = new TestRouterConfig();
    private NetworkConfigListener networkConfigListener;
    private DeviceListener deviceListener;
    private MastershipService mastershipService = new InternalMastershipServiceTest();
    private InterfaceListener interfaceListener;
    private ApplicationService applicationService;

    @Before
    public void setUp() {
        networkConfigListener = createMock(NetworkConfigListener.class);
        deviceService = new TestDeviceService();
        deviceListener = createMock(DeviceListener.class);

        interfaceListener = createMock(InterfaceListener.class);
        deviceService.addListener(deviceListener);
        setUpInterfaceService();
        interfaceService = new InternalInterfaceService();
        interfaceService.addListener(interfaceListener);
        networkConfigService = new TestNetworkConfigService();
        networkConfigService.addListener(networkConfigListener);
        flowObjectiveService = createMock(FlowObjectiveService.class);
        applicationService = createNiceMock(ApplicationService.class);
        replay(applicationService);
        setUpFlowObjectiveService();
        controlPlaneRedirectManager.coreService = coreService;
        controlPlaneRedirectManager.flowObjectiveService = flowObjectiveService;
        controlPlaneRedirectManager.networkConfigService = networkConfigService;
        controlPlaneRedirectManager.interfaceService = interfaceService;
        controlPlaneRedirectManager.deviceService = deviceService;
        controlPlaneRedirectManager.hostService = createNiceMock(HostService.class);
        controlPlaneRedirectManager.mastershipService = mastershipService;
        controlPlaneRedirectManager.applicationService = applicationService;
        controlPlaneRedirectManager.activate();
        verify(flowObjectiveService);
    }

    /**
     * Tests adding new Device to a openflow router.
     */
    @Test
    public void testAddDevice() {
        ConnectPoint sw1eth4 = new ConnectPoint(DEVICE_ID, PortNumber.portNumber(4));
        List<InterfaceIpAddress> interfaceIpAddresses = new ArrayList<>();
        interfaceIpAddresses.add(
                new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24"))
        );
        interfaceIpAddresses.add(
                new InterfaceIpAddress(IpAddress.valueOf("2000::ff"), IpPrefix.valueOf("2000::ff/120"))
        );

        Interface sw1Eth4 = new Interface(sw1eth4.deviceId().toString(), sw1eth4, interfaceIpAddresses,
                MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE);
        interfaces.add(sw1Eth4);
        EasyMock.reset(flowObjectiveService);
        setUpFlowObjectiveService();
        deviceListener.event(new DeviceEvent(DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED, dev3));
        verify(flowObjectiveService);
    }

    /**
     * Tests adding while updating the networkConfig.
     */
    @Test
    public void testUpdateNetworkConfig() {
        ConnectPoint sw1eth4 = new ConnectPoint(DEVICE_ID, PortNumber.portNumber(4));
        List<InterfaceIpAddress> interfaceIpAddresses = new ArrayList<>();
        interfaceIpAddresses.add(
                new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24"))
        );
        interfaceIpAddresses.add(
                new InterfaceIpAddress(IpAddress.valueOf("2000::ff"), IpPrefix.valueOf("2000::ff/120"))
        );

        Interface sw1Eth4 = new Interface(sw1eth4.deviceId().toString(), sw1eth4, interfaceIpAddresses,
                MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE);
        interfaces.add(sw1Eth4);
        EasyMock.reset(flowObjectiveService);
        setUpFlowObjectiveService();
        networkConfigListener
                .event(new NetworkConfigEvent(Type.CONFIG_UPDATED, dev3, RoutingService.ROUTER_CONFIG_CLASS));
        networkConfigService.addListener(networkConfigListener);
        verify(flowObjectiveService);
    }

    /**
     * Tests adding while updating the networkConfig.
     */
    @Test
    public void testAddInterface() {
        ConnectPoint sw1eth4 = new ConnectPoint(DEVICE_ID, PortNumber.portNumber(4));
        List<InterfaceIpAddress> interfaceIpAddresses = new ArrayList<>();
        interfaceIpAddresses.add(
                new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24"))
        );
        interfaceIpAddresses.add(
                new InterfaceIpAddress(IpAddress.valueOf("2000::ff"), IpPrefix.valueOf("2000::ff/120"))
        );

        Interface sw1Eth4 = new Interface(sw1eth4.deviceId().toString(), sw1eth4, interfaceIpAddresses,
                MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE);
        interfaces.add(sw1Eth4);

        EasyMock.reset(flowObjectiveService);
        expect(flowObjectiveService.allocateNextId()).andReturn(1).anyTimes();

        setUpInterfaceConfiguration(sw1Eth4, true);
        replay(flowObjectiveService);
        interfaceListener.event(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, sw1Eth4, 500L));
        verify(flowObjectiveService);
    }

    @Test
    public void testRemoveInterface() {
        ConnectPoint sw1eth4 = new ConnectPoint(DEVICE_ID, PortNumber.portNumber(4));
        List<InterfaceIpAddress> interfaceIpAddresses = new ArrayList<>();
        interfaceIpAddresses.add(
                new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24"))
        );
        interfaceIpAddresses.add(
                new InterfaceIpAddress(IpAddress.valueOf("2000::ff"), IpPrefix.valueOf("2000::ff/120"))
        );

        Interface sw1Eth4 = new Interface(sw1eth4.deviceId().toString(), sw1eth4, interfaceIpAddresses,
                MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE);
        EasyMock.reset(flowObjectiveService);
        expect(flowObjectiveService.allocateNextId()).andReturn(1).anyTimes();

        setUpInterfaceConfiguration(sw1Eth4, false);
        replay(flowObjectiveService);
        interfaceListener.event(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, sw1Eth4, 500L));
        verify(flowObjectiveService);
    }

    /**
     * Setup flow Configuration for all configured Interfaces.
     *
     **/
    private void setUpFlowObjectiveService() {
        expect(flowObjectiveService.allocateNextId()).andReturn(1).anyTimes();
        for (Interface intf : interfaceService.getInterfaces()) {
            setUpInterfaceConfiguration(intf, true);
        }
        replay(flowObjectiveService);
    }

    /**
     * Setting up flowobjective expectations for basic forwarding and ospf.
     **/
    private void setUpInterfaceConfiguration(Interface intf, boolean install) {
        DeviceId deviceId = controlPlaneConnectPoint.deviceId();
        PortNumber controlPlanePort = controlPlaneConnectPoint.port();

        for (InterfaceIpAddress ip : intf.ipAddresses()) {
            int cpNextId, intfNextId;

            cpNextId = modifyNextObjective(deviceId, controlPlanePort,
                    VlanId.vlanId(ControlPlaneRedirectManager.ASSIGNED_VLAN), true, install);
            intfNextId = modifyNextObjective(deviceId, intf.connectPoint().port(),
                    VlanId.vlanId(ControlPlaneRedirectManager.ASSIGNED_VLAN), true, install);

            // IP to router
            TrafficSelector toSelector = buildIPDstSelector(
                    ip.ipAddress().toIpPrefix(),
                    intf.connectPoint().port(),
                    null,
                    intf.mac(),
                    intf.vlan());

            flowObjectiveService.forward(deviceId, buildForwardingObjective(toSelector, null,
                                                                            cpNextId, install, ACL_PRIORITY));
            expectLastCall().once();

            // IP from router
            TrafficSelector fromSelector = buildIPSrcSelector(
                    ip.ipAddress().toIpPrefix(),
                    controlPlanePort,
                    intf.mac(),
                    null,
                    intf.vlan()
            );

            flowObjectiveService.forward(deviceId, buildForwardingObjective(fromSelector, null,
                                                                            intfNextId, install, ACL_PRIORITY));
            expectLastCall().once();

            TrafficTreatment puntTreatment = DefaultTrafficTreatment.builder().punt().build();
            if (ip.ipAddress().isIp4()) {
                // ARP to router
                toSelector = buildArpSelector(
                        intf.connectPoint().port(),
                        intf.vlan(),
                        null,
                        null
                );

                flowObjectiveService.forward(deviceId, buildForwardingObjective(toSelector, puntTreatment,
                                                                                cpNextId, install, ACL_PRIORITY + 1));
                expectLastCall().once();

                // ARP from router
                fromSelector = buildArpSelector(
                        controlPlanePort,
                        intf.vlan(),
                        ip.ipAddress().getIp4Address(),
                        intf.mac()
                );

                flowObjectiveService.forward(deviceId,
                                             buildForwardingObjective(fromSelector, puntTreatment,
                                                                      intfNextId, install, ACL_PRIORITY + 1));
                expectLastCall().once();
            } else {
                // NDP solicitation to router
                toSelector = buildNdpSelector(
                        intf.connectPoint().port(),
                        intf.vlan(),
                        null,
                        NEIGHBOR_SOLICITATION,
                        null
                );

                flowObjectiveService.forward(deviceId, buildForwardingObjective(toSelector, puntTreatment,
                                                                                cpNextId, install, ACL_PRIORITY + 1));
                expectLastCall().once();

                // NDP solicitation from router
                fromSelector = buildNdpSelector(
                        controlPlanePort,
                        intf.vlan(),
                        ip.ipAddress().toIpPrefix(),
                        NEIGHBOR_SOLICITATION,
                        intf.mac()
                );

                flowObjectiveService.forward(deviceId,
                                             buildForwardingObjective(fromSelector, puntTreatment,
                                                                      intfNextId, install, ACL_PRIORITY + 1));

                // NDP advertisement to router
                toSelector = buildNdpSelector(
                        intf.connectPoint().port(),
                        intf.vlan(),
                        null,
                        NEIGHBOR_ADVERTISEMENT,
                        null
                );

                flowObjectiveService.forward(deviceId, buildForwardingObjective(toSelector, puntTreatment,
                                                                                cpNextId, install, ACL_PRIORITY + 1));
                expectLastCall().once();

                // NDP advertisement from router
                fromSelector = buildNdpSelector(
                        controlPlanePort,
                        intf.vlan(),
                        ip.ipAddress().toIpPrefix(),
                        NEIGHBOR_ADVERTISEMENT,
                        intf.mac()
                );

                flowObjectiveService.forward(deviceId,
                                             buildForwardingObjective(fromSelector, puntTreatment,
                                                                      intfNextId, install, ACL_PRIORITY + 1));
            }
        }
        // setting expectations for ospf forwarding.
        TrafficSelector toSelector = DefaultTrafficSelector.builder().matchInPort(intf.connectPoint().port())
                .matchEthType(EthType.EtherType.IPV4.ethType().toShort()).matchVlanId(intf.vlan())
                .matchIPProtocol((byte) OSPF_IP_PROTO).build();

        modifyNextObjective(deviceId, controlPlanePort, VlanId.vlanId((short) 4094), true, install);
        flowObjectiveService.forward(controlPlaneConnectPoint.deviceId(),
                buildForwardingObjective(toSelector, null, 1, install, 40001));
        expectLastCall().once();
    }

    /**
     * Setup expectations on flowObjectiveService.next for NextObjective.
     *
     **/
    private int modifyNextObjective(DeviceId deviceId, PortNumber portNumber, VlanId vlanId, boolean popVlan,
            boolean modifyFlag) {
        NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder().withId(1)
                .withType(NextObjective.Type.SIMPLE).fromApp(APPID);

        TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder();
        if (popVlan) {
            ttBuilder.popVlan();
        }
        ttBuilder.setOutput(portNumber);

        TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
        metabuilder.matchVlanId(vlanId);

        nextObjBuilder.withMeta(metabuilder.build());
        nextObjBuilder.addTreatment(ttBuilder.build());
        if (modifyFlag) {
            flowObjectiveService.next(deviceId, nextObjBuilder.add());
            expectLastCall().once();
        } else {
            flowObjectiveService.next(deviceId, nextObjBuilder.remove());
            expectLastCall().once();
        }
        return 1;
    }

    /**
     * Setup Interface expectation for all Testcases.
     **/
    private void setUpInterfaceService() {
        List<InterfaceIpAddress> interfaceIpAddresses1 = new ArrayList<>();
        interfaceIpAddresses1
                .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"), IpPrefix.valueOf("192.168.10.0/24")));
        Interface sw1Eth1 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH1, interfaceIpAddresses1,
                MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE);
        interfaces.add(sw1Eth1);

        List<InterfaceIpAddress> interfaceIpAddresses2 = new ArrayList<>();
        interfaceIpAddresses2
                .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"), IpPrefix.valueOf("192.168.20.0/24")));
        Interface sw1Eth2 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH2, interfaceIpAddresses2,
                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE);
        interfaces.add(sw1Eth2);

        List<InterfaceIpAddress> interfaceIpAddresses3 = new ArrayList<>();
        interfaceIpAddresses3
                .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"), IpPrefix.valueOf("192.168.30.0/24")));
        Interface sw1Eth3 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH3, interfaceIpAddresses3,
                MacAddress.valueOf("00:00:00:00:00:03"), VlanId.NONE);
        interfaces.add(sw1Eth3);

    }

    private ForwardingObjective buildForwardingObjective(TrafficSelector selector, TrafficTreatment treatment,
            int nextId, boolean add, int priority) {
        DefaultForwardingObjective.Builder fobBuilder = DefaultForwardingObjective.builder();
        fobBuilder.withSelector(selector);
        if (treatment != null) {
            fobBuilder.withTreatment(treatment);
        }
        if (nextId != -1) {
            fobBuilder.nextStep(nextId);
        }
        fobBuilder.fromApp(APPID).withPriority(priority).withFlag(ForwardingObjective.Flag.VERSATILE);

        return add ? fobBuilder.add() : fobBuilder.remove();
    }

    private class TestCoreService extends CoreServiceAdapter {

        @Override
        public ApplicationId getAppId(String name) {
            return APPID;
        }

        @Override
        public ApplicationId registerApplication(String name) {
            return new TestApplicationId(name);
        }

    }

    private class TestDeviceService extends DeviceServiceAdapter {

        @Override
        public boolean isAvailable(DeviceId deviceId) {
            boolean flag = false;
            if (deviceId.equals(controlPlaneConnectPoint.deviceId())) {
                flag = true;
            }
            return flag;
        }

        @Override
        public void addListener(DeviceListener listener) {
            ControlPlaneRedirectManagerTest.this.deviceListener = listener;
        }

    }

    private class TestRouterConfig extends RouterConfig {

        @Override
        public ConnectPoint getControlPlaneConnectPoint() {
            return controlPlaneConnectPoint;
        }

        @Override
        public boolean getOspfEnabled() {
            return true;
        }

        @Override
        public List<String> getInterfaces() {
            ArrayList<String> interfaces = new ArrayList<>();
            interfaces.add("of:0000000000000001");
            interfaces.add("of:0000000000000001/2");
            interfaces.add("of:0000000000000001/3");
            return interfaces;
        }

    }

    private class TestNetworkConfigService extends NetworkConfigServiceAdapter {

        @Override
        public void addListener(NetworkConfigListener listener) {
            ControlPlaneRedirectManagerTest.this.networkConfigListener = listener;
        }

        @Override
        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
            return (C) ControlPlaneRedirectManagerTest.this.routerConfig;
        }

    }

    private static class TestApplicationId implements ApplicationId {

        private final String name;
        private final short id;

        public TestApplicationId(String name) {
            this.name = name;
            this.id = (short) Objects.hash(name);
        }

        public static ApplicationId create(String name) {
            return new TestApplicationId(name);
        }

        @Override
        public short id() {
            return id;
        }

        @Override
        public String name() {
            return name;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + id;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            TestApplicationId other = (TestApplicationId) obj;
            if (id != other.id) {
                return false;
            }
            if (name == null) {
                if (other.name != null) {
                    return false;
                }
            } else if (!name.equals(other.name)) {
                return false;
            }
            return true;
        }
    }

    private class InternalMastershipServiceTest extends MastershipServiceAdapter {

        @Override
        public boolean isLocalMaster(DeviceId deviceId) {
            boolean flag = deviceId.equals(controlPlaneConnectPoint.deviceId());
            return flag;
        }

    }

    private class InternalInterfaceService extends InterfaceServiceAdapter {

        @Override
        public void addListener(InterfaceListener listener) {
            ControlPlaneRedirectManagerTest.this.interfaceListener = listener;
        }

        @Override
        public Set<Interface> getInterfaces() {
            return interfaces;
        }

        @Override
        public Set<Interface> getInterfacesByPort(ConnectPoint port) {
            Set<Interface> setIntf = new HashSet<Interface>();
            for (Interface intf : interfaces) {
                if (intf.connectPoint().equals(port)) {
                    setIntf.add(intf);
                }
            }
            return setIntf;
        }

        @Override
        public Interface getMatchingInterface(IpAddress ip) {
            Interface intff = null;
            for (Interface intf : interfaces) {
                for (InterfaceIpAddress address : intf.ipAddresses()) {
                    if (address.ipAddress().equals(ip)) {
                        intff = intf;
                        break;
                    }
                }
            }

            return intff;
        }

    }
}
