/*
 * 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.sdxl3.config;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.ConfigApplyDelegate;
import org.onosproject.sdxl3.SdxL3;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

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

public class SdxProvidersConfigTest {
    private static final ApplicationId APP_ID =
            new TestApplicationId(SdxL3.SDX_L3_APP);
    private static final String KEY = "key";

    private static final String NAME1 = "peer1";
    private static final String IP_STRING1 = "10.0.1.1";
    private static final IpAddress IP1 = IpAddress.valueOf(IP_STRING1);
    private static final String PORT_STRING1 = "of:00000000000000a1/1";
    private static final ConnectPoint PORT1 =
            ConnectPoint.deviceConnectPoint(PORT_STRING1);
    private static final String INTF_NAME1 = "conn_point1";

    private static final String IP_STRING2 = "10.0.2.1";
    private static final IpAddress IP2 = IpAddress.valueOf(IP_STRING2);
    private static final String PORT_STRING2 = "of:00000000000000a1/2";
    private static final ConnectPoint PORT2 =
            ConnectPoint.deviceConnectPoint(PORT_STRING2);
    private static final String INTF_NAME2 = "conn_point2";

    private static final String NAME3 = "new_peer";
    private static final String IP_STRING3 = "10.0.3.1";
    private static final String PORT_STRING3 = "of:00000000000000a1/3";
    private static final ConnectPoint PORT3 =
            ConnectPoint.deviceConnectPoint(PORT_STRING3);
    private static final IpAddress IP3 = IpAddress.valueOf(IP_STRING3);
    private static final String INTF_NAME3 = "conn_point3";

    private static final String JSON_TREE = "{\"" + SdxProvidersConfig.PEERS + "\"" +
            ": [{\"" + SdxProvidersConfig.NAME + "\" : \"" + NAME1 + "\", " +
            "\"" + SdxProvidersConfig.IP + "\" : \"" + IP_STRING1 + "\", " +
            "\"" + SdxProvidersConfig.CONN_POINT + "\" : \"" + PORT_STRING1 + "\", " +
            "\"" + SdxProvidersConfig.INTF_NAME + "\" : \"" + INTF_NAME1 + "\"}, " +
            "{ \"" + SdxProvidersConfig.IP + "\" : \"" + IP_STRING2 + "\", " +
            "\"" + SdxProvidersConfig.CONN_POINT + "\" : \"" + PORT_STRING2 + "\", " +
            "\"" + SdxProvidersConfig.INTF_NAME + "\" : \"" + INTF_NAME2 + "\"}]}";

    private static final String EMPTY_JSON_TREE = "{ }";

    private Set<SdxProvidersConfig.PeerConfig> peers = new HashSet<>();
    private SdxProvidersConfig.PeerConfig peer1;

    private SdxProvidersConfig peersConfig = new SdxProvidersConfig();
    private SdxProvidersConfig emptyPeersConfig = new SdxProvidersConfig();

    private final ConfigApplyDelegate delegate = new MockCfgDelegate();
    private final ObjectMapper mapper = new ObjectMapper();

    @Before
    public void setUp()  throws Exception {
        peers = createPeers();
        JsonNode node = new ObjectMapper().readTree(JSON_TREE);
        peersConfig.init(APP_ID, KEY, node, mapper, delegate);
        JsonNode emptyTree = new ObjectMapper().readTree(EMPTY_JSON_TREE);
        emptyPeersConfig.init(APP_ID, KEY, emptyTree, mapper, delegate);
    }

    /**
     * Tests if peers can be retrieved from JSON.
     */
    @Test
    public void testBgpPeers() throws Exception {
        assertEquals(peers, peersConfig.bgpPeers());
    }

    /**
     * Tests if interface name can be retrieved for given peer's IP.
     */
    @Test
    public void testGetInterfaceNameForPeer() throws Exception {
        assertEquals(INTF_NAME1, peersConfig.getInterfaceNameForPeer(IP1));
    }

    /**
     * Tests addition of new peer.
     */
    @Test
    public void testAddPeer() throws Exception {
        int initialSize = peersConfig.bgpPeers().size();
        SdxProvidersConfig.PeerConfig newPeer = createNewPeer();
        peersConfig.addPeer(newPeer);
        assertEquals(initialSize + 1, peersConfig.bgpPeers().size());
        peers.add(newPeer);
        assertEquals(peers, peersConfig.bgpPeers());
    }

    /**
     * Tests addition of new peer to empty configuration.
     */
    @Test
    public void testAddPeerToEmpty() throws Exception {
        emptyPeersConfig.addPeer(createNewPeer());
        assertFalse(emptyPeersConfig.bgpPeers().isEmpty());
    }

    /**
     * Tests getting peer configuration based on given name.
     */
    @Test
    public void testGetPeerForName() throws Exception {
        assertEquals(peer1, peersConfig.getPeerForName(Optional.of(NAME1)));
    }

    /**
     * Tests getting peer configuration based on given IP.
     */
    @Test
    public void testGetPeerForIp() throws Exception {
        assertEquals(peer1, peersConfig.getPeerForIp(IP1));
    }

    /**
     * Tests removing peer details based on given IP.
     */
    @Test
    public void testRemovePeer() throws Exception {
        int initialSize = peersConfig.bgpPeers().size();
        peersConfig.removePeer(IP1);
        assertEquals(initialSize - 1, peersConfig.bgpPeers().size());
        peers.remove(peer1);
        assertEquals(peers, peersConfig.bgpPeers());    }

    private Set<SdxProvidersConfig.PeerConfig> createPeers() {
        Set<SdxProvidersConfig.PeerConfig> peers = Sets.newHashSet();

        peer1 = new SdxProvidersConfig.
                PeerConfig(Optional.of(NAME1), IP1, PORT1, INTF_NAME1);
        peers.add(peer1);
        peers.add(new SdxProvidersConfig.
                PeerConfig(Optional.empty(), IP2, PORT2, INTF_NAME2));

        return peers;
    }

    private SdxProvidersConfig.PeerConfig createNewPeer() {
        return new SdxProvidersConfig.
                PeerConfig(Optional.of(NAME3), IP3, PORT3, INTF_NAME3);
    }

    private class MockCfgDelegate implements ConfigApplyDelegate {

        @Override
        public void onApply(@SuppressWarnings("rawtypes") Config config) {
            config.apply();
        }

    }
}

