/*
 * Copyright 2017-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.opencord.igmpproxy.impl;

import static org.junit.Assert.assertEquals;
import static org.onlab.junit.TestTools.assertAfter;

import java.util.List;

import com.google.common.collect.Maps;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.VlanId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.net.flow.FlowRuleServiceAdapter;
import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;

import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
import org.onosproject.store.service.TestStorageService;
import org.opencord.igmpproxy.IgmpStatisticType;
import org.opencord.igmpproxy.IgmpStatisticsEvent;

import com.google.common.collect.Lists;
import org.opencord.igmpproxy.IgmpStatisticsEventListener;

/**
 * Set of tests of the ONOS application component for IGMP Statistics.
 */
public class IgmpStatisticsTest extends IgmpManagerBase {

    private static final int WAIT_TIMEOUT = 500;

    private IgmpManager igmpManager;

    private IgmpStatisticsManager igmpStatisticsManager;

    private MockIgmpStatisticsEventListener mockListener = new MockIgmpStatisticsEventListener();

    // Set up the IGMP application.
    @Before
    public void setUp() {
        igmpManager = new IgmpManager();
        igmpManager.igmpLeadershipService = new TestIgmpLeaderShipService();
        igmpManager.coreService = new CoreServiceAdapter();
        igmpManager.mastershipService = new MockMastershipService();
        igmpManager.flowObjectiveService = new FlowObjectiveServiceAdapter();
        igmpManager.deviceService = new MockDeviceService();
        igmpManager.packetService = new MockPacketService();
        igmpManager.flowRuleService = new FlowRuleServiceAdapter();
        igmpManager.multicastService = new TestMulticastRouteService();
        igmpManager.sadisService = new MockSadisService();
        igmpManager.groupMemberStore = new TestGroupMemberStoreService();
        StateMachineManager stateMachineService = new StateMachineManager();
        stateMachineService.stateMachineStore = new TestStateMachineStoreService(Maps.newConcurrentMap());
        stateMachineService.activate(new MockComponentContext());
        igmpManager.stateMachineService = stateMachineService;
        igmpStatisticsManager = new IgmpStatisticsManager();
        igmpStatisticsManager.cfgService = new MockCfgService();
        igmpStatisticsManager.addListener(mockListener);
        TestUtils.setField(igmpStatisticsManager, "eventDispatcher", new TestEventDispatcher());
        igmpStatisticsManager.storageService = new TestStorageService();
        igmpStatisticsManager.leadershipManager = new TestIgmpLeaderShipService();
        igmpStatisticsManager.clusterCommunicationService = new ClusterCommunicationServiceAdapter();
        igmpStatisticsManager.activate(new MockComponentContext());
        igmpManager.igmpStatisticsManager = this.igmpStatisticsManager;
        // By default - we send query messages
        StateMachineManager.sendQuery = true;
    }

    // Tear Down the IGMP application.
    @After
    public void tearDown() {
        igmpStatisticsManager.removeListener(mockListener);
        igmpStatisticsManager.deactivate();
        igmpManager.stateMachineService.clearAllMaps();
    }

    //Test Igmp Statistics.
    @Test
    public void testIgmpStatistics() throws InterruptedException {
        StateMachineManager.sendQuery = false;
        igmpManager.networkConfig = new TestNetworkConfigRegistry(false);
        igmpManager.activate();

        //IGMPv3 Join
        flagForPacket = false;
        Ethernet igmpv3MembershipReportPkt = IgmpSender.getInstance().buildIgmpV3Join(GROUP_IP, SOURCE_IP_OF_A);
        sendPacket(igmpv3MembershipReportPkt);
        synchronized (savedPackets) {
            savedPackets.wait(WAIT_TIMEOUT);
        }
        //Leave
        flagForPacket = false;
        Ethernet igmpv3LeavePkt = IgmpSender.getInstance().buildIgmpV3Leave(GROUP_IP, SOURCE_IP_OF_A);
        sendPacket(igmpv3LeavePkt);
        synchronized (savedPackets) {
            savedPackets.wait(WAIT_TIMEOUT);
        }

        assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
                assertEquals((long) 2, igmpStatisticsManager
                        .getStat(IgmpStatisticType.TOTAL_MSG_RECEIVED).longValue()));
        assertEquals(1L, igmpStatisticsManager.getStat(IgmpStatisticType.IGMP_JOIN_REQ).longValue());
        assertEquals(2L, igmpStatisticsManager
                .getStat(IgmpStatisticType.IGMP_V3_MEMBERSHIP_REPORT).longValue());
        assertEquals(1L, igmpStatisticsManager
                .getStat(IgmpStatisticType.IGMP_SUCCESS_JOIN_RE_JOIN_REQ).longValue());
        assertEquals(1L, igmpStatisticsManager
                .getStat(IgmpStatisticType.UNCONFIGURED_GROUP_COUNTER).longValue());
        assertEquals(2L, igmpStatisticsManager
                .getStat(IgmpStatisticType.VALID_IGMP_PACKET_COUNTER).longValue());
        assertEquals(1L, igmpStatisticsManager
                .getStat(IgmpStatisticType.IGMP_CHANNEL_JOIN_COUNTER).longValue());
        assertEquals(1L, igmpStatisticsManager
                .getStat(IgmpStatisticType.IGMP_LEAVE_REQ).longValue());
        assertEquals(2L, igmpStatisticsManager
                .getStat(IgmpStatisticType.IGMP_MSG_RECEIVED).longValue());
        assertEquals(2L, igmpStatisticsManager
                .getStat(IgmpStatisticType.IGMP_VALID_CHECKSUM_COUNTER).longValue());

    }

    //Test packet with Unknown Multicast IpAddress
    @Test
    public void testIgmpUnknownMulticastIpAddress() throws InterruptedException {
        StateMachineManager.sendQuery = false;

        igmpManager.networkConfig = new TestNetworkConfigRegistry(false);
        igmpManager.activate();

        Ethernet firstPacket =
                IgmpSender.getInstance().buildIgmpV3Join(UNKNOWN_GRP_IP, SOURCE_IP_OF_A);
        // Sending first packet
        sendPacket(firstPacket);
        assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
                assertEquals((long) 1, igmpStatisticsManager
                        .getStat(IgmpStatisticType.FAIL_JOIN_REQ_UNKNOWN_MULTICAST_IP_COUNTER).longValue()));
    }

    //Test Igmp Query Statistics.
    @Test
    public void testIgmpQueryStatistics() throws InterruptedException {
        igmpManager.networkConfig = new TestNetworkConfigRegistry(false);
        igmpManager.activate();

        flagForQueryPacket = true;
        //IGMPV3 Group Specific Membership Query packet
        Ethernet igmpv3MembershipQueryPkt = IgmpSender.getInstance().
                buildIgmpV3Query(GROUP_IP, SOURCE_IP_OF_A, VlanId.MAX_VLAN);
        sendPacket(igmpv3MembershipQueryPkt);

        //IGMPV3 General Membership Query packet
        Ethernet igmpv3MembershipQueryPkt1 =
                IgmpSender.getInstance().buildIgmpV3Query(Ip4Address.valueOf(0), SOURCE_IP_OF_A, VlanId.MAX_VLAN);
        sendPacket(igmpv3MembershipQueryPkt1);
        assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
                assertEquals(igmpStatisticsManager
                        .getStat(IgmpStatisticType.IGMP_GRP_AND_SRC_SPESIFIC_MEMBERSHIP_QUERY).longValue(), 101));
        assertEquals(igmpStatisticsManager
                .getStat(IgmpStatisticType.IGMP_GENERAL_MEMBERSHIP_QUERY).longValue(), 1);
        assertEquals(igmpStatisticsManager.getStat(IgmpStatisticType.CURRENT_GRP_NUMBER_COUNTER).longValue(), 1);
    }

    //Test Events
    @Test
    public void testIgmpStatisticsEvent() {
        final int waitEventGeneration = igmpStatisticsManager.statisticsGenerationPeriodInSeconds * 1000;
        //assert that event listened as the app activates
        assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
                assertEquals(mockListener.events.size(), 1));

        assertAfter(waitEventGeneration / 2, waitEventGeneration, () ->
                assertEquals(mockListener.events.size(), 2));

        for (IgmpStatisticsEvent event : mockListener.events) {
            assertEquals(event.type(), IgmpStatisticsEvent.Type.STATS_UPDATE);
        }
    }

    //Test packet with Unknown Wrong Membership mode
    @Test
    public void testWrongIgmpPacket() throws InterruptedException {
        StateMachineManager.sendQuery = false;

        igmpManager.networkConfig = new TestNetworkConfigRegistry(false);
        igmpManager.activate();

        Ethernet firstPacket = buildWrongIgmpPacket(GROUP_IP, SOURCE_IP_OF_A);
        // Sending first packet
        sendPacket(firstPacket);
        assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
                assertEquals((long) 1, igmpStatisticsManager
                        .getStat(IgmpStatisticType.REPORTS_RX_WITH_WRONG_MODE_COUNTER).longValue()));
    }

    //Test packet with Unknown IGMP type.
    @Test
    public void testUnknownIgmpPacket() throws InterruptedException {
        StateMachineManager.sendQuery = false;

        igmpManager.networkConfig = new TestNetworkConfigRegistry(false);
        igmpManager.activate();

        Ethernet firstPacket = buildUnknownIgmpPacket(GROUP_IP, SOURCE_IP_OF_A);
        // Sending first packet
        sendPacket(firstPacket);
        assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
                assertEquals((long) 1, igmpStatisticsManager
                        .getStat(IgmpStatisticType.UNKNOWN_IGMP_TYPE_PACKETS_RX_COUNTER).longValue()));
    }

    //Test packet with Insufficient Permission.
    @Test
    public void testSufficientPermission() throws InterruptedException {
        StateMachineManager.sendQuery = false;

        flagForPermission = true;
        igmpManager.networkConfig = new TestNetworkConfigRegistry(false);
        igmpManager.activate();

        Ethernet firstPacket = IgmpSender.getInstance().buildIgmpV3Join(GROUP_IP, SOURCE_IP_OF_A);
        // Sending first packet
        sendPacket(firstPacket);
        assertAfter(WAIT_TIMEOUT, WAIT_TIMEOUT * 2, () ->
                assertEquals((long) 1, igmpStatisticsManager
                        .getStat(IgmpStatisticType.FAIL_JOIN_REQ_INSUFF_PERMISSION_ACCESS_COUNTER).longValue()));
    }

    public class MockIgmpStatisticsEventListener implements IgmpStatisticsEventListener {
        protected List<IgmpStatisticsEvent> events = Lists.newArrayList();

        @Override
        public void event(IgmpStatisticsEvent event) {
            events.add(event);
        }

    }
}
