/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.net.neighbour.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.edge.EdgePortServiceAdapter;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketService;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.onosproject.net.neighbour.impl.DefaultNeighbourMessageContext.createContext;

/**
 * Unit tests for DefaultNeighbourMessageActions.
 */
public class DefaultNeighbourMessageActionsTest {

    private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
    private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
    private static final ConnectPoint CP3 = ConnectPoint.deviceConnectPoint("of:0000000000000002/1");

    private static final List<ConnectPoint> EDGE_PORTS =
            ImmutableList.<ConnectPoint>builder()
                    .add(CP1)
                    .add(CP2)
                    .add(CP3)
                    .build();

    private static final MacAddress MAC1 = MacAddress.valueOf(1);
    private static final MacAddress MAC2 = MacAddress.valueOf(2);
    private static final IpAddress IP1 = IpAddress.valueOf(1);
    private static final IpAddress IP2 = IpAddress.valueOf(2);

    private static final VlanId VLAN1 = VlanId.vlanId((short) 1);

    private static final Interface INTF1 = NeighbourTestUtils.intf(CP1, IP1, MAC1, VLAN1);
    private static final Interface INTF2 = NeighbourTestUtils.intf(CP2, IP2, MAC2, VLAN1);

    private DefaultNeighbourMessageActions actions;
    private PacketService packetService;

    @Before
    public void setUp() throws Exception {
        packetService = createMock(PacketService.class);
        actions = new DefaultNeighbourMessageActions(packetService, new TestEdgeService());
    }

    @Test
    public void reply() throws Exception {
        Ethernet request = NeighbourTestUtils.createArpRequest(IP1);

        Ip4Address ip4Address = INTF1.ipAddressesList().get(0).ipAddress().getIp4Address();
        Ethernet response = ARP.buildArpReply(ip4Address, MAC2, request);

        packetService.emit(outbound(response, CP1));
        expectLastCall().once();
        replay(packetService);

        actions.reply(createContext(request, CP1, null), MAC2);

        verify(packetService);
    }

    @Test
    public void forwardToConnectPoint() {
        Ethernet request = NeighbourTestUtils.createArpRequest(IP1);

        packetService.emit(outbound(request, CP2));
        expectLastCall().once();
        replay(packetService);

        actions.forward(createContext(request, CP1, null), CP2);

        verify(packetService);
    }

    @Test
    public void forwardToInterface() {
        Ethernet request = NeighbourTestUtils.createArpRequest(IP1);

        Ethernet forwardedRequest = request.duplicate();
        forwardedRequest.setSourceMACAddress(INTF2.mac());
        forwardedRequest.setVlanID(INTF2.vlan().toShort());

        packetService.emit(outbound(forwardedRequest, CP2));
        expectLastCall().once();
        replay(packetService);

        actions.forward(createContext(request, CP1, null), INTF2);

        verify(packetService);
    }

    @Test
    public void flood() {
        Ethernet request = NeighbourTestUtils.createArpRequest(IP1);

        // Expect the packet to be emitted out all ports apart from the in port
        Sets.difference(Sets.newLinkedHashSet(EDGE_PORTS), Collections.singleton(CP1))
                .forEach(cp -> {
                    packetService.emit(outbound(request, cp));
                    expectLastCall().once();
                });
        replay(packetService);

        actions.flood(createContext(request, CP1, null));

        verify(packetService);
    }

    private static OutboundPacket outbound(Ethernet packet, ConnectPoint outPort) {
        TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(outPort.port()).build();
        return new DefaultOutboundPacket(outPort.deviceId(),
                treatment, ByteBuffer.wrap(packet.serialize()));
    }

    private class TestEdgeService extends EdgePortServiceAdapter {

        @Override
        public boolean isEdgePoint(ConnectPoint point) {
            return true;
        }

        @Override
        public Iterable<ConnectPoint> getEdgePoints() {
            return EDGE_PORTS;
        }

    }

}
