/*
 * 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.incubator.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.incubator.net.neighbour.impl.DefaultNeighbourMessageContext.createContext;
import static org.onosproject.incubator.net.neighbour.impl.NeighbourTestUtils.createArpRequest;
import static org.onosproject.incubator.net.neighbour.impl.NeighbourTestUtils.intf;

/**
 * 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 = intf(CP1, IP1, MAC1, VLAN1);
    private static final Interface INTF2 = 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 = 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 = 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 = createArpRequest(IP1);

        Ethernet forwardedRequest = (Ethernet) request.clone();
        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 = 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;
        }

    }

}
