/*
 * Copyright 2016 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.netconf.ctl;

import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.netconf.NetconfDevice;
import org.onosproject.netconf.NetconfDeviceFactory;
import org.onosproject.netconf.NetconfDeviceInfo;
import org.onosproject.netconf.NetconfDeviceListener;
import org.onosproject.netconf.NetconfDeviceOutputEvent;
import org.onosproject.netconf.NetconfDeviceOutputEventListener;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Optional;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

/**
 * Unit tests for the Netconf controller implementation test.
 */
public class NetconfControllerImplTest {
    NetconfControllerImpl ctrl;

    //DeviceInfo
    NetconfDeviceInfo deviceInfo1;
    NetconfDeviceInfo deviceInfo2;
    NetconfDeviceInfo badDeviceInfo3;

    //Devices & DeviceId
    NetconfDevice device1;
    DeviceId deviceId1;
    NetconfDevice device2;
    DeviceId deviceId2;

    //Events
    NetconfDeviceOutputEvent eventForDeviceInfo1;
    NetconfDeviceOutputEvent eventForDeviceInfo2;

    private Map<DeviceId, NetconfDevice> reflectedDeviceMap;
    private NetconfDeviceOutputEventListener reflectedDownListener;

    //Test Device IP addresses and ports
    private static final String DEVICE_1_IP = "10.10.10.11";
    private static final String DEVICE_2_IP = "10.10.10.12";
    private static final String BAD_DEVICE_IP = "10.10.10.13";

    private static final int DEVICE_1_PORT = 11;
    private static final int DEVICE_2_PORT = 12;
    private static final int BAD_DEVICE_PORT = 13;


    @Before
    public void setUp() throws Exception {
        ctrl = new NetconfControllerImpl();
        ctrl.deviceFactory = new TestNetconfDeviceFactory();

        //Creating mock devices
        deviceInfo1 = new NetconfDeviceInfo("device1", "001", IpAddress.valueOf(DEVICE_1_IP), DEVICE_1_PORT);
        deviceInfo2 = new NetconfDeviceInfo("device2", "002", IpAddress.valueOf(DEVICE_2_IP), DEVICE_2_PORT);
        badDeviceInfo3 = new NetconfDeviceInfo("device3", "003", IpAddress.valueOf(BAD_DEVICE_IP), BAD_DEVICE_PORT);

        device1 = new TestNetconfDevice(deviceInfo1);
        deviceId1 = deviceInfo1.getDeviceId();
        device2 = new TestNetconfDevice(deviceInfo2);
        deviceId2 = deviceInfo2.getDeviceId();

        //Adding to the map for testing get device calls.
        Field field1 = ctrl.getClass().getDeclaredField("netconfDeviceMap");
        field1.setAccessible(true);
        reflectedDeviceMap = (Map<DeviceId, NetconfDevice>) field1.get(ctrl);
        reflectedDeviceMap.put(deviceId1, device1);
        reflectedDeviceMap.put(deviceId2, device2);

        //Creating mock events for testing NetconfDeviceOutputEventListener
        Field field2 = ctrl.getClass().getDeclaredField("downListener");
        field2.setAccessible(true);
        reflectedDownListener = (NetconfDeviceOutputEventListener) field2.get(ctrl);

        eventForDeviceInfo1 = new NetconfDeviceOutputEvent(NetconfDeviceOutputEvent.Type.DEVICE_NOTIFICATION, null,
                null, Optional.of(1), deviceInfo1);
        eventForDeviceInfo2 = new NetconfDeviceOutputEvent(NetconfDeviceOutputEvent.Type.DEVICE_UNREGISTERED, null,
                null, Optional.of(2), deviceInfo2);
    }

    @After
    public void tearDown() {
        ctrl.deactivate();
    }

    /**
     * Test to add DeviceListeners,
     * and also to check whether the netconfDeviceListeners set is
     * updating or not which was present in NetconfControllerImpl class.
     */
    @Test
    public void testAddRemoveDeviceListener() {
        NetconfDeviceListener deviceListener1 = EasyMock.createMock(NetconfDeviceListener.class);
        NetconfDeviceListener deviceListener2 = EasyMock.createMock(NetconfDeviceListener.class);
        NetconfDeviceListener deviceListener3 = EasyMock.createMock(NetconfDeviceListener.class);

        ctrl.addDeviceListener(deviceListener1);
        ctrl.addDeviceListener(deviceListener2);
        ctrl.addDeviceListener(deviceListener3);
        assertThat("Incorrect number of listeners", ctrl.netconfDeviceListeners, hasSize(3));
        assertThat("Not matching listeners", ctrl.netconfDeviceListeners, hasItems(deviceListener1,
                deviceListener2, deviceListener3));

        ctrl.removeDeviceListener(deviceListener1);
        assertThat("Incorrect number of listeners", ctrl.netconfDeviceListeners, hasSize(2));
        assertThat("Not matching listeners", ctrl.netconfDeviceListeners, hasItems(deviceListener2, deviceListener3));
    }

    @Test
    public void testGetNetconfDevice() {
        NetconfDevice fetchedDevice1 = ctrl.getNetconfDevice(deviceId1);
        assertThat("Incorrect device fetched", fetchedDevice1, is(device1));

        NetconfDevice fetchedDevice2 = ctrl.getNetconfDevice(deviceId2);
        assertThat("Incorrect device fetched", fetchedDevice2, is(device2));
    }

    @Test
    public void testGetNetconfDeviceWithIPPort() {
        NetconfDevice fetchedDevice1 = ctrl.getNetconfDevice(IpAddress.valueOf(DEVICE_1_IP), DEVICE_1_PORT);
        assertEquals("Incorrect device fetched", fetchedDevice1.getDeviceInfo().ip(), device1.getDeviceInfo().ip());

        NetconfDevice fetchedDevice2 = ctrl.getNetconfDevice(IpAddress.valueOf(DEVICE_2_IP), DEVICE_2_PORT);
        assertEquals("Incorrect device fetched", fetchedDevice2.getDeviceInfo().ip(), device2.getDeviceInfo().ip());
    }

    /**
     * Check for bad device connection. In this case the device map shouldn't get modified.
     */
    @Test(expected = NetconfException.class)
    public void testConnectBadDevice() throws Exception {
        reflectedDeviceMap.clear();
        try {
            ctrl.connectDevice(badDeviceInfo3);
        } finally {
            assertEquals("Incorrect device connection", 0, ctrl.getDevicesMap().size());
        }
    }

    /**
     * Check for correct device connection. In this case the device map get modified.
     */
    @Test
    public void testConnectCorrectDevice() throws Exception {
        reflectedDeviceMap.clear();
        ctrl.connectDevice(deviceInfo1);
        ctrl.connectDevice(deviceInfo2);
        assertTrue("Incorrect device connection", ctrl.getDevicesMap().containsKey(deviceId1));
        assertTrue("Incorrect device connection", ctrl.getDevicesMap().containsKey(deviceId2));
        assertEquals("Incorrect device connection", 2, ctrl.getDevicesMap().size());
    }


    /**
     * Check for connect devices already added to the map.
     */
    @Test
    public void testConnectAlreadyExistingDevice() throws Exception {
        NetconfDevice alreadyExistingDevice1 = ctrl.connectDevice(deviceInfo1);
        NetconfDevice alreadyExistingDevice2 = ctrl.connectDevice(deviceInfo2);
        assertEquals("Incorrect device connection", alreadyExistingDevice1.getDeviceInfo().getDeviceId(),
                deviceInfo1.getDeviceId());
        assertEquals("Incorrect device connection", alreadyExistingDevice2.getDeviceInfo().getDeviceId(),
                deviceInfo2.getDeviceId());
    }

    /**
     * Check for removeDevice exception.
     */
    @Test
    public void testRemoveDevice() throws Exception {
        ctrl.removeDevice(deviceInfo1);
        assertFalse("Incorrect device removal", ctrl.getDevicesMap().containsKey(deviceId1));
    }

    /**
     * Test to get the connected device map.
     */
    @Test
    public void testGetDevicesMap() {
        assertEquals("Incorrect device map size", 2, ctrl.getDevicesMap().size());
    }

    /**
     * Test to check whether the DeviceDownEventListener removes the device from the map when session
     * for a particular device getting closed.
     */
    @Test
    public void testDeviceDownEventListener() throws Exception {
        reflectedDeviceMap.clear();
        ctrl.connectDevice(deviceInfo1);
        boolean result1 = reflectedDownListener.isRelevant(eventForDeviceInfo2);
        assertFalse("Irrelevant Device Event", result1);
        assertEquals("Incorrect device map size", 1, ctrl.getDevicesMap().size());
        reflectedDownListener.event(eventForDeviceInfo1);
        assertEquals("Incorrect device map size", 1, ctrl.getDevicesMap().size());
        ctrl.connectDevice(deviceInfo2);
        boolean result2 = reflectedDownListener.isRelevant(eventForDeviceInfo2);
        assertTrue("Irrelevant Device Event", result2);
        assertEquals("Incorrect device map size", 2, ctrl.getDevicesMap().size());
        reflectedDownListener.event(eventForDeviceInfo2);
        assertEquals("Incorrect device map size", 1, ctrl.getDevicesMap().size());
    }

    /**
     * Mock NetconfDeviceFactory class.
     */
    private class TestNetconfDeviceFactory implements NetconfDeviceFactory {

        @Override
        public NetconfDevice createNetconfDevice(NetconfDeviceInfo netconfDeviceInfo) throws NetconfException {
            return new TestNetconfDevice(netconfDeviceInfo);
        }
    }

    /**
     * Mock NetconfDeviceImpl class, used for creating test devices.
     */
    protected class TestNetconfDevice implements NetconfDevice {
        private NetconfDeviceInfo netconfDeviceInfo;
        private boolean deviceState = false;
        private NetconfSession netconfSession;

        public TestNetconfDevice(NetconfDeviceInfo deviceInfo) throws NetconfException {
            netconfDeviceInfo = deviceInfo;
            if (netconfDeviceInfo.ip() != badDeviceInfo3.ip()) {
                netconfSession = EasyMock.createMock(NetconfSession.class);
                deviceState = true;
            } else {
                throw new NetconfException("Cannot create Connection and Session");
            }
        }

        @Override
        public boolean isActive() {
            return deviceState;
        }

        @Override
        public NetconfSession getSession() {
            return netconfSession;
        }

        @Override
        public void disconnect() {
            deviceState = false;
            netconfSession = null;
        }

        @Override
        public NetconfDeviceInfo getDeviceInfo() {
            return netconfDeviceInfo;
        }

    }
}
