/*
 * Copyright 2015-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.aaa.impl;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.onlab.junit.TestUtils;
import org.onlab.packet.BasePacket;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.EAP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.RADIUS;
import org.onlab.packet.RADIUSAttribute;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.LeadershipServiceAdapter;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.event.DefaultEventSinkRegistry;
import org.onosproject.event.Event;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.event.EventSink;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
import org.onosproject.store.service.TestStorageService;
import org.opencord.aaa.AaaConfig;
import org.slf4j.Logger;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicReference;

import static com.google.common.base.Preconditions.checkState;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.onosproject.net.intent.TestTools.assertAfter;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Set of tests of the ONOS application component.
 */
@RunWith(Parameterized.class)
public class AaaManagerTest extends AaaTestBase {

    // Change this to have more run with mvn
    @Parameterized.Parameters
    public static Object[][] data() {
        return new Object[1][0];
    }

    static final String BAD_IP_ADDRESS = "198.51.100.0";

    private final Logger log = getLogger(getClass());

    private AaaManager aaaManager;
    private AaaStatisticsManager aaaStatisticsManager;

    class AaaManagerWithoutRadiusServer extends AaaManager {
        protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
            savePacket(radiusPacket);
        }
    }
    /**
     * Mocks the AAAConfig class to force usage of an unroutable address for the
     * RADIUS server.
     */
    static class MockAaaConfig extends AaaConfig {
        @Override
        public InetAddress radiusIp() {
            try {
                return InetAddress.getByName(BAD_IP_ADDRESS);
            } catch (UnknownHostException ex) {
                // can't happen
                throw new IllegalStateException(ex);
            }
        }
    }

    static final class TestLeadershipService extends LeadershipServiceAdapter {
        @Override
        public NodeId getLeader(String path) {
            return new ClusterServiceAdapter().getLocalNode().id();
        }
    }

    /**
     * Mocks the network config registry.
     */
    @SuppressWarnings("unchecked")
    private static final class TestNetworkConfigRegistry
            extends NetworkConfigRegistryAdapter {
        @Override
        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
            AaaConfig aaaConfig = new MockAaaConfig();
            return (C) aaaConfig;
        }
    }

    public static class TestEventDispatcher extends DefaultEventSinkRegistry
            implements EventDeliveryService {
        @Override
        @SuppressWarnings("unchecked")
        public synchronized void post(Event event) {
            EventSink sink = getSink(event.getClass());
            checkState(sink != null, "No sink for event %s", event);
            sink.process(event);
        }

        @Override
        public void setDispatchTimeLimit(long millis) {
        }

        @Override
        public long getDispatchTimeLimit() {
            return 0;
        }
    }

    /**
     * Sets up the services required by the AAA application.
     */
    @Before
    public void setUp() {
        aaaManager = new AaaManagerWithoutRadiusServer();
        aaaManager.netCfgService = new TestNetworkConfigRegistry();
        aaaManager.coreService = new CoreServiceAdapter();
        aaaManager.packetService = new MockPacketService();
        aaaManager.deviceService = new TestDeviceService();
        aaaManager.sadisService = new MockSadisService();
        aaaManager.cfgService = new MockCfgService();
        aaaManager.storageService = new TestStorageService();
        aaaStatisticsManager = new AaaStatisticsManager();
        aaaStatisticsManager.storageService = new TestStorageService();
        aaaStatisticsManager.clusterService = new ClusterServiceAdapter();
        aaaStatisticsManager.leadershipService = new TestLeadershipService();
        aaaStatisticsManager.clusterCommunicationService = new ClusterCommunicationServiceAdapter();
        aaaManager.radiusOperationalStatusService = new RadiusOperationalStatusManager();
        TestUtils.setField(aaaStatisticsManager, "eventDispatcher", new TestEventDispatcher());
        aaaStatisticsManager.activate(new MockComponentContext());
        aaaManager.aaaStatisticsManager = this.aaaStatisticsManager;
        TestUtils.setField(aaaManager, "eventDispatcher", new TestEventDispatcher());


        aaaManager.activate(new AaaTestBase.MockComponentContext());
    }

    /**
     * Tears down the AAA application.
     */
    @After
    public void tearDown() {
        aaaManager.deactivate(new AaaTestBase.MockComponentContext());
    }

    /**
     * Extracts the RADIUS packet from a packet sent by the supplicant.
     *
     * @param radius RADIUS packet sent by the supplicant
     * @throws DeserializationException if deserialization of the packet contents
     *         fails.
     */
    private void checkRadiusPacketFromSupplicant(RADIUS radius)
            throws DeserializationException {
        assertThat(radius, notNullValue());

        EAP eap = radius.decapsulateMessage();
        assertThat(eap, notNullValue());
    }

    /**
     * Fetches the sent packet at the given index. The requested packet
     * must be the last packet on the list.
     *
     * @param index index into sent packets array
     * @return packet
     */
    private BasePacket fetchPacket(int index) {
        BasePacket packet = savedPackets.get(index);
        assertThat(packet, notNullValue());
        return packet;
    }

    /**
     * Tests the authentication path through the AAA application.
     *
     * @throws DeserializationException if packed deserialization fails.
     */
    @Test
    public void testAuthentication() throws Exception {

        //  (1) Supplicant start up

        Ethernet startPacket = constructSupplicantStartPacket();
        sendPacket(startPacket);
        assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
            Ethernet responsePacket = (Ethernet) fetchPacket(0);
            checkRadiusPacket(aaaManager, responsePacket, EAP.ATTR_IDENTITY);

            //  (2) Supplicant identify

            Ethernet identifyPacket = null;
            try {
                identifyPacket = constructSupplicantIdentifyPacket(null,
                                                                   EAP.ATTR_IDENTITY, (byte) 3, null);
            } catch (Exception e) {
                log.error(e.getMessage());
                fail();
            }
            sendPacket(identifyPacket);
        });
        assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
            RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
            AtomicReference<Byte> reqId = new AtomicReference<>(radiusIdentifyPacket.getIdentifier());

            try {
                checkRadiusPacketFromSupplicant(radiusIdentifyPacket);
            } catch (DeserializationException e) {
                log.error(e.getMessage());
                fail();
            }

            assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
            assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
                       is("testuser"));

            IpAddress nasIp =
                    IpAddress.valueOf(IpAddress.Version.INET,
                                      radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
                                              .getValue());
            assertThat(nasIp.toString(), is(aaaManager.nasIpAddress.getHostAddress()));

            // (3) RADIUS MD5 challenge

            RADIUS radiusCodeAccessChallengePacket =
                    constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5,
                                                             reqId.get(), aaaManager.radiusSecret.getBytes());
            aaaManager.handleRadiusPacket(radiusCodeAccessChallengePacket);
        });
        assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {

            //  State machine should have been created by now

            StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);
            assertThat(stateMachine, notNullValue());
            assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));

            Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2);
            checkRadiusPacket(aaaManager, radiusChallengeMD5Packet, EAP.ATTR_MD5);

            // (4) Supplicant MD5 response
            try {
                Ethernet md5RadiusPacket =
                        constructSupplicantIdentifyPacket(stateMachine,
                                                          EAP.ATTR_MD5,
                                                          stateMachine.challengeIdentifier(),
                                                          radiusChallengeMD5Packet);
                sendPacket(md5RadiusPacket);
            } catch (Exception e) {
                log.error(e.getMessage());
                fail();
            }
        });

        //  State machine should have been created by now

        StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);

        assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {


            RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
            try {
                checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
            } catch (Exception e) {
                log.error(e.getMessage());
                fail();
            }
            //assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 9));
            AtomicReference<Byte> reqId = new AtomicReference<>(responseMd5RadiusPacket.getIdentifier());
            assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));

            //  State machine should be in pending state

            assertThat(stateMachine, notNullValue());
            assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));

            // (5) RADIUS Success

            RADIUS successPacket =
                    constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT,
                                                             EAP.SUCCESS, reqId.get(),
                                                             aaaManager.radiusSecret.getBytes());
            aaaManager.handleRadiusPacket((successPacket));
        });
        assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
            Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4);

            checkRadiusPacket(aaaManager, supplicantSuccessPacket, EAP.SUCCESS);

            //  State machine should be in authorized state

            assertThat(stateMachine, notNullValue());
            assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
        });
    }

    @Test
    public void testRemoveAuthentication() {
        Ethernet startPacket = constructSupplicantStartPacket();
        sendPacket(startPacket);
        assertAfter(ASSERTION_DELAY, ASSERTION_LENGTH, () -> {
            StateMachine stateMachine = aaaManager.getStateMachine(SESSION_ID);

            assertThat(stateMachine, notNullValue());
            assertThat(stateMachine.state(), is(StateMachine.STATE_STARTED));

            aaaManager.removeAuthenticationStateByMac(stateMachine.supplicantAddress());

            assertThat(aaaManager.getStateMachine(SESSION_ID), nullValue());
        });
    }

    /**
     * Tests the default configuration.
     */
    @Test
    public void testConfig() {
        assertThat(aaaManager.nasIpAddress.getHostAddress(), is(AaaConfig.DEFAULT_NAS_IP));
        assertThat(aaaManager.nasMacAddress, is(AaaConfig.DEFAULT_NAS_MAC));
        assertThat(aaaManager.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS));
        assertThat(aaaManager.radiusMacAddress, is(AaaConfig.DEFAULT_RADIUS_MAC));
    }
}
