/*
 * Copyright 2016-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.incubator.net.virtual.impl.provider;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.IdGenerator;
import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualHost;
import org.onosproject.incubator.net.virtual.VirtualLink;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleServiceAdapter;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.LinkWeigher;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyServiceAdapter;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import static org.junit.Assert.assertEquals;

public class DefaultVirtualFlowRuleProviderTest {
    private static final ProviderId PID = new ProviderId("of", "foo");

    private static final DeviceId DID1 = DeviceId.deviceId("of:001");
    private static final DeviceId DID2 = DeviceId.deviceId("of:002");
    private static final PortNumber PORT_NUM1 = PortNumber.portNumber(1);
    private static final PortNumber PORT_NUM2 = PortNumber.portNumber(2);

    private static final DefaultAnnotations ANNOTATIONS =
            DefaultAnnotations.builder().set("foo", "bar").build();

    private static final Device DEV1 =
            new DefaultDevice(PID, DID1, Device.Type.SWITCH, "", "", "", "", null);
    private static final Device DEV2 =
            new DefaultDevice(PID, DID2, Device.Type.SWITCH, "", "", "", "", null);
    private static final Port PORT11 =
            new DefaultPort(DEV1, PORT_NUM1, true, ANNOTATIONS);
    private static final Port PORT12 =
            new DefaultPort(DEV1, PORT_NUM2, true, ANNOTATIONS);
    private static final Port PORT21 =
            new DefaultPort(DEV2, PORT_NUM1, true, ANNOTATIONS);
    private static final Port PORT22 =
            new DefaultPort(DEV2, PORT_NUM2, true, ANNOTATIONS);

    private static final ConnectPoint CP11 = new ConnectPoint(DID1, PORT_NUM1);
    private static final ConnectPoint CP12 = new ConnectPoint(DID1, PORT_NUM2);
    private static final ConnectPoint CP21 = new ConnectPoint(DID2, PORT_NUM1);
    private static final ConnectPoint CP22 = new ConnectPoint(DID2, PORT_NUM2);
    private static final Link LINK1 = DefaultLink.builder()
            .src(CP12).dst(CP21).providerId(PID).type(Link.Type.DIRECT).build();

    private static final NetworkId VNET_ID = NetworkId.networkId(1);
    private static final DeviceId VDID = DeviceId.deviceId("of:100");

    private static final VirtualNetwork VNET = new DefaultVirtualNetwork(
            VNET_ID, TenantId.tenantId("t1"));
    private static final VirtualDevice VDEV =
            new DefaultVirtualDevice(VNET_ID, VDID);
    private static final VirtualPort VPORT1 =
            new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM1, CP11);
    private static final VirtualPort VPORT2 =
            new DefaultVirtualPort(VNET_ID, VDEV, PORT_NUM2, CP22);

    private static final int TIMEOUT = 10;


    protected DefaultVirtualFlowRuleProvider virtualProvider;

    private ApplicationId vAppId;

    @Before
    public void setUp() {
        virtualProvider = new DefaultVirtualFlowRuleProvider();

        virtualProvider.deviceService = new TestDeviceService();
        virtualProvider.coreService = new TestCoreService();
        virtualProvider.virtualNetworkAdminService =
                new TestVirtualNetworkAdminService();
        virtualProvider.topologyService = new TestTopologyService();
        virtualProvider.flowRuleService = new TestFlowRuleService();
        virtualProvider.providerRegistryService = new VirtualProviderManager();

        virtualProvider.activate();
        vAppId = new TestApplicationId(0, "Virtual App");
    }

    @After
    public void tearDown() {
        virtualProvider.deactivate();
        virtualProvider.deviceService = null;
        virtualProvider.coreService = null;
    }

    @Test
    public void virtualizeFlowRuleWithInPort() {
        TrafficSelector ts = DefaultTrafficSelector.builder()
                .matchInPort(PORT_NUM1).build();
        TrafficTreatment tr = DefaultTrafficTreatment.builder()
                .setOutput(PORT_NUM2).build();

        FlowRule r1 = DefaultFlowRule.builder()
                .forDevice(VDID)
                .withSelector(ts)
                .withTreatment(tr)
                .withPriority(10)
                .fromApp(vAppId)
                .makeTemporary(TIMEOUT)
                .build();

        virtualProvider.applyFlowRule(VNET_ID, r1);

        assertEquals("2 rules should exist", 2,
                     virtualProvider.flowRuleService.getFlowRuleCount());

        Set<FlowEntry> phyRules = new HashSet<>();
        for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
            phyRules.add(i);
        }
        for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
            phyRules.add(i);
        }

        FlowRule in = null;
        FlowRule out = null;

        for (FlowRule rule : phyRules) {

            L2ModificationInstruction i = (L2ModificationInstruction)
                    rule.treatment().allInstructions().get(0);

            if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
                in = rule;
            } else {
                out = rule;
            }

        }

        assertEquals(DID1, in.deviceId());
        assertEquals(DID2, out.deviceId());
    }

    @Test
    public void virtualizeFlowRuleWithoutInPort() {
        TrafficSelector ts = DefaultTrafficSelector.builder().build();
        TrafficTreatment tr = DefaultTrafficTreatment.builder()
                .setOutput(PORT_NUM2).build();

        FlowRule r1 = DefaultFlowRule.builder()
                .forDevice(VDID)
                .withSelector(ts)
                .withTreatment(tr)
                .withPriority(10)
                .fromApp(vAppId)
                .makeTemporary(TIMEOUT)
                .build();

        virtualProvider.applyFlowRule(VNET_ID, r1);

        assertEquals("3 rules should exist", 3,
                     virtualProvider.flowRuleService.getFlowRuleCount());

        FlowRule inFromDID1 = null;
        FlowRule inFromDID2 = null;
        FlowRule out = null;

        Set<FlowEntry> phyRules = new HashSet<>();
        for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID1)) {
            phyRules.add(i);
        }
        for (FlowEntry i : virtualProvider.flowRuleService.getFlowEntries(DID2)) {
            phyRules.add(i);
        }

        for (FlowRule rule : phyRules) {
            for (Instruction inst : rule.treatment().allInstructions()) {
                if (inst.type() == Instruction.Type.L2MODIFICATION) {
                    L2ModificationInstruction i = (L2ModificationInstruction) inst;
                    if (i.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
                        inFromDID1 = rule;
                        break;
                    } else {
                        out = rule;
                        break;
                    }
                } else {
                    inFromDID2 = rule;
                    break;
                }
            }
        }

        assertEquals(DID1, inFromDID1.deviceId());
        assertEquals(DID2, inFromDID2.deviceId());
        assertEquals(DID2, out.deviceId());
    }

    @Test
    public void removeVirtualizeFlowRule() {
        TrafficSelector ts = DefaultTrafficSelector.builder().build();
        TrafficTreatment tr = DefaultTrafficTreatment.builder()
                .setOutput(PORT_NUM2).build();

        FlowRule r1 = DefaultFlowRule.builder()
                .forDevice(VDID)
                .withSelector(ts)
                .withTreatment(tr)
                .withPriority(10)
                .fromApp(vAppId)
                .makeTemporary(TIMEOUT)
                .build();

        virtualProvider.removeFlowRule(VNET_ID, r1);

        assertEquals("0 rules should exist", 0,
                     virtualProvider.flowRuleService.getFlowRuleCount());
    }


    private static class TestDeviceService extends DeviceServiceAdapter {
        @Override
        public int getDeviceCount() {
            return 2;
        }

        @Override
        public Iterable<Device> getDevices() {
            return ImmutableList.of(DEV1, DEV2);
        }

        @Override
        public Iterable<Device> getAvailableDevices() {
            return getDevices();
        }

        @Override
        public Device getDevice(DeviceId deviceId) {
            return deviceId.equals(DID2) ? DEV2 : DEV1;
        }
    }

    private static class TestCoreService extends CoreServiceAdapter {

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

        @Override
        public IdGenerator getIdGenerator(String topic) {
            return new IdGenerator() {
                private AtomicLong counter = new AtomicLong(0);

                @Override
                public long getNewId() {
                    return counter.getAndIncrement();
                }
            };
        }
    }

    private static class TestApplicationId extends DefaultApplicationId {
        public TestApplicationId(int id, String name) {
            super(id, name);
        }
    }

    private static class TestVirtualNetworkAdminService
            implements VirtualNetworkAdminService {

        @Override
        public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
            return null;
        }

        @Override
        public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
            return ImmutableSet.of(VDEV);
        }

        @Override
        public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
            return null;
        }

        @Override
        public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
            return null;
        }

        @Override
        public Set<VirtualPort> getVirtualPorts(NetworkId networkId,
                                                DeviceId deviceId) {
            return ImmutableSet.of(VPORT1, VPORT2);
        }

        @Override
        public <T> T get(NetworkId networkId, Class<T> serviceClass) {
            return null;
        }

        @Override
        public ServiceDirectory getServiceDirectory() {
            return null;
        }

        @Override
        public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
            return null;
        }

        @Override
        public void registerTenantId(TenantId tenantId) {

        }

        @Override
        public void unregisterTenantId(TenantId tenantId) {

        }

        @Override
        public Set<TenantId> getTenantIds() {
            return null;
        }

        @Override
        public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
            return null;
        }

        @Override
        public void removeVirtualNetwork(NetworkId networkId) {

        }

        @Override
        public VirtualDevice createVirtualDevice(NetworkId networkId,
                                                 DeviceId deviceId) {
            return null;
        }

        @Override
        public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {

        }

        @Override
        public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
                                             MacAddress mac, VlanId vlan,
                                             HostLocation location,
                                             Set<IpAddress> ips) {
            return null;
        }

        @Override
        public void removeVirtualHost(NetworkId networkId, HostId hostId) {

        }

        @Override
        public VirtualLink createVirtualLink(NetworkId networkId,
                                             ConnectPoint src, ConnectPoint dst) {
            return null;
        }

        @Override
        public void removeVirtualLink(NetworkId networkId,
                                      ConnectPoint src, ConnectPoint dst) {

        }

        @Override
        public VirtualPort createVirtualPort(NetworkId networkId,
                                             DeviceId deviceId,
                                             PortNumber portNumber,
                                             ConnectPoint realizedBy) {
            return null;
        }

        @Override
        public void bindVirtualPort(NetworkId networkId,
                                    DeviceId deviceId,
                                    PortNumber portNumber,
                                    ConnectPoint realizedBy) {

        }

        @Override
        public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
                                      PortNumber portNumber) {

        }

        @Override
        public void addListener(VirtualNetworkListener listener) {

        }

        @Override
        public void removeListener(VirtualNetworkListener listener) {

        }
    }

    private static class TestTopologyService extends TopologyServiceAdapter {

        @Override
        public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
            DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
                                               100, ANNOTATIONS);
            return ImmutableSet.of(path);
        }

        @Override
        public Set<Path> getPaths(Topology topology, DeviceId src,
                                  DeviceId dst, LinkWeight weight) {
            DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
                                               100, ANNOTATIONS);
            return ImmutableSet.of(path);
        }

        @Override
        public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
                                  LinkWeigher weigher) {
            DefaultPath path = new DefaultPath(PID, ImmutableList.of(LINK1),
                                               100, ANNOTATIONS);
            return ImmutableSet.of(path);
        }

    }

    private static class TestFlowRuleService extends FlowRuleServiceAdapter {
        static Set<FlowRule> ruleCollection = new HashSet<>();

        @Override
        public int getFlowRuleCount() {
            return ruleCollection.size();
        }

        @Override
        public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
            return ruleCollection.stream()
                    .filter(r -> r.deviceId().equals(deviceId))
                    .map(r -> new DefaultFlowEntry(r))
                    .collect(Collectors.toSet());
        }

        @Override
        public void applyFlowRules(FlowRule... flowRules) {
            for (FlowRule rule : flowRules) {
                ruleCollection.add(rule);
            }
        }

        @Override
        public void removeFlowRules(FlowRule... flowRules) {
            Set<FlowRule> candidates = new HashSet<>();
            for (FlowRule rule : flowRules) {
                ruleCollection.stream()
                        .filter(r -> r.exactMatch(rule))
                        .forEach(candidates::add);
            }
            ruleCollection.removeAll(candidates);
        }
    }
}
