/*
 * Copyright 2015 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.incubator.net.intf.impl;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.incubator.net.config.basics.ConfigException;
import org.onosproject.incubator.net.config.basics.InterfaceConfig;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.host.InterfaceIpAddress;

import java.util.Collections;
import java.util.Map;
import java.util.Set;

import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertNull;

/**
 * Unit tests for InterfaceManager.
 */
public class InterfaceManagerTest {
    private static final Class<InterfaceConfig> CONFIG_CLASS = InterfaceConfig.class;

    private static final int NUM_INTERFACES = 4;

    private Set<ConnectPoint> subjects = Sets.newHashSet();
    private Map<ConnectPoint, InterfaceConfig> configs = Maps.newHashMap();

    private Set<Interface> interfaces = Sets.newHashSet();

    private NetworkConfigListener listener;

    private InterfaceManager interfaceManager;

    @Before
    public void setUp() throws Exception {
        for (int i = 0; i < NUM_INTERFACES; i++) {
            ConnectPoint cp = createConnectPoint(i);
            subjects.add(cp);

            Interface intf = createInterface(i);

            interfaces.add(intf);

            InterfaceConfig ic = new TestInterfaceConfig(cp, Sets.newHashSet(intf));

            configs.put(cp, ic);
        }

        TestNetworkConfigService configService =
                new TestNetworkConfigService(subjects, configs);

        interfaceManager = new InterfaceManager();
        interfaceManager.configService = configService;
        interfaceManager.activate();
    }

    private Interface createInterface(int i) {
        ConnectPoint cp = createConnectPoint(i);

        InterfaceIpAddress ia = InterfaceIpAddress.valueOf("192.168." + i + ".1/24");

        Interface intf = new Interface(cp,
                Sets.newHashSet(ia),
                MacAddress.valueOf(i),
                VlanId.vlanId((short) i));

        return intf;
    }

    private ConnectPoint createConnectPoint(int i) {
        return  ConnectPoint.deviceConnectPoint("of:000000000000000" + i + "/1");
    }

    @Test
    public void testGetInterfaces() throws Exception {
        assertEquals(interfaces, interfaceManager.getInterfaces());
    }

    @Test
    public void testGetInterfacesByPort() throws Exception {
        ConnectPoint cp = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");

        Set<Interface> byPort = Collections.singleton(createInterface(1));

        assertEquals(byPort, interfaceManager.getInterfacesByPort(cp));
    }

    @Test
    public void testGetInterfacesByIp() throws Exception {
        IpAddress ip = Ip4Address.valueOf("192.168.2.1");

        Set<Interface> byIp = Collections.singleton(createInterface(2));

        assertEquals(byIp, interfaceManager.getInterfacesByIp(ip));
    }

    @Test
    public void testGetMatchingInterface() throws Exception {
        IpAddress ip = Ip4Address.valueOf("192.168.1.100");

        Interface matchingIntf = createInterface(1);

        assertEquals(matchingIntf, interfaceManager.getMatchingInterface(ip));

        // Searching for an IP with no match should return null
        ip = Ip4Address.valueOf("1.1.1.1");

        assertNull(interfaceManager.getMatchingInterface(ip));
    }

    @Test
    public void testGetInterfacesByVlan() throws Exception {
        VlanId vlanId = VlanId.vlanId((short) 1);

        Set<Interface> byVlan = Collections.singleton(createInterface(1));

        assertEquals(byVlan, interfaceManager.getInterfacesByVlan(vlanId));
    }

    @Test
    public void testAddInterface() throws Exception {
        // Create a new InterfaceConfig which will get added
        VlanId vlanId = VlanId.vlanId((short) 1);
        ConnectPoint cp = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
        Interface newIntf = new Interface(cp,
                Collections.emptySet(),
                MacAddress.valueOf(100),
                vlanId);

        InterfaceConfig ic = new TestInterfaceConfig(cp, Collections.singleton(newIntf));

        subjects.add(cp);
        configs.put(cp, ic);
        interfaces.add(newIntf);

        NetworkConfigEvent event = new NetworkConfigEvent(
                NetworkConfigEvent.Type.CONFIG_ADDED, cp, CONFIG_CLASS);

        assertEquals(NUM_INTERFACES, interfaceManager.getInterfaces().size());

        // Send in a config event containing a new interface config
        listener.event(event);

        // Check the new interface exists in the InterfaceManager's inventory
        assertEquals(interfaces, interfaceManager.getInterfaces());
        assertEquals(NUM_INTERFACES + 1, interfaceManager.getInterfaces().size());

        // There are now two interfaces with vlan ID 1
        Set<Interface> byVlan = Sets.newHashSet(createInterface(1), newIntf);
        assertEquals(byVlan, interfaceManager.getInterfacesByVlan(vlanId));
    }

    @Test
    public void testUpdateInterface() throws Exception {
        ConnectPoint cp = createConnectPoint(1);

        // Create an interface that is the same as the existing one, but adds a
        // new IP address
        Interface intf = createInterface(1);
        Set<InterfaceIpAddress> addresses = Sets.newHashSet(intf.ipAddresses());
        addresses.add(InterfaceIpAddress.valueOf("192.168.100.1/24"));
        intf = new Interface(intf.connectPoint(), addresses, intf.mac(), intf.vlan());

        // Create a new interface on the same connect point as the existing one
        InterfaceIpAddress newAddr = InterfaceIpAddress.valueOf("192.168.101.1/24");
        Interface newIntf = new Interface(cp,
                Collections.singleton(newAddr),
                MacAddress.valueOf(101),
                VlanId.vlanId((short) 101));

        Set<Interface> interfaces = Sets.newHashSet(intf, newIntf);

        // New interface config updates the existing interface and adds a new
        // interface to the same connect point
        InterfaceConfig ic = new TestInterfaceConfig(cp, interfaces);

        configs.put(cp, ic);

        NetworkConfigEvent event = new NetworkConfigEvent(
                NetworkConfigEvent.Type.CONFIG_UPDATED, cp, CONFIG_CLASS);

        // Send in the event signalling the interfaces for this connect point
        // have been updated
        listener.event(event);

        assertEquals(NUM_INTERFACES + 1, interfaceManager.getInterfaces().size());
        assertEquals(interfaces, interfaceManager.getInterfacesByPort(cp));
    }

    @Test
    public void testRemoveInterface() throws Exception {
        ConnectPoint cp = createConnectPoint(1);

        NetworkConfigEvent event = new NetworkConfigEvent(
                NetworkConfigEvent.Type.CONFIG_REMOVED, cp, CONFIG_CLASS);

        assertEquals(NUM_INTERFACES, interfaceManager.getInterfaces().size());

        // Send in a config event removing an interface config
        listener.event(event);

        assertEquals(NUM_INTERFACES - 1, interfaceManager.getInterfaces().size());
    }

    /**
     * Test version of NetworkConfigService which allows us to pass in subjects
     * and InterfaceConfigs directly.
     */
    private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
        private final Set<ConnectPoint> subjects;
        private final Map<ConnectPoint, InterfaceConfig> configs;

        public TestNetworkConfigService(Set<ConnectPoint> subjects,
                                        Map<ConnectPoint, InterfaceConfig> configs) {
            this.subjects = subjects;
            this.configs = configs;
        }

        @Override
        public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass,
                                                           Class<C> configClass) {
            return (Set<S>) subjects;
        }

        @Override
        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
            return (C) configs.get(subject);
        }

        @Override
        public void addListener(NetworkConfigListener listener) {
            InterfaceManagerTest.this.listener = listener;
        }
    }

    /**
     * Test version of InterfaceConfig where we can inject interfaces directly,
     * rather than parsing them from JSON.
     */
    private class TestInterfaceConfig extends InterfaceConfig {
        private final ConnectPoint subject;
        private final Set<Interface> interfaces;

        @Override
        public ConnectPoint subject() {
            return subject;
        }

        public TestInterfaceConfig(ConnectPoint subject, Set<Interface> interfaces) {
            this.subject = subject;
            this.interfaces = interfaces;
        }

        @Override
        public Set<Interface> getInterfaces() throws ConfigException {
            return interfaces;
        }
    }

}
