/*
 * Copyright 2019-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.onosproject.k8snode.impl;

import com.google.common.collect.Lists;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.LeadershipServiceAdapter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.event.Event;
import org.onosproject.k8snode.api.DefaultK8sNode;
import org.onosproject.k8snode.api.K8sNode;
import org.onosproject.k8snode.api.K8sNodeEvent;
import org.onosproject.k8snode.api.K8sNodeListener;
import org.onosproject.k8snode.api.K8sNodeState;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.store.service.TestStorageService;

import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.onosproject.k8snode.api.K8sNode.Type.MINION;
import static org.onosproject.k8snode.api.K8sNodeEvent.Type.K8S_NODE_COMPLETE;
import static org.onosproject.k8snode.api.K8sNodeEvent.Type.K8S_NODE_CREATED;
import static org.onosproject.k8snode.api.K8sNodeEvent.Type.K8S_NODE_INCOMPLETE;
import static org.onosproject.k8snode.api.K8sNodeEvent.Type.K8S_NODE_REMOVED;
import static org.onosproject.k8snode.api.K8sNodeEvent.Type.K8S_NODE_UPDATED;
import static org.onosproject.k8snode.api.K8sNodeState.COMPLETE;
import static org.onosproject.k8snode.api.K8sNodeState.INCOMPLETE;
import static org.onosproject.k8snode.api.K8sNodeState.INIT;
import static org.onosproject.net.Device.Type.SWITCH;

/**
 * Unit tests for Kubernetes node manager.
 */
public class K8sNodeManagerTest {

    private static final ApplicationId TEST_APP_ID = new DefaultApplicationId(1, "test");

    private static final String ERR_SIZE = "Number of nodes did not match";
    private static final String ERR_NOT_MATCH = "Node did not match";
    private static final String ERR_NOT_FOUND = "Node did not exist";

    private static final String MINION_1_HOSTNAME = "minion_1";
    private static final String MINION_2_HOSTNAME = "minion_2";
    private static final String MINION_3_HOSTNAME = "minion_3";

    private static final Device MINION_1_INTG_DEVICE = createDevice(1);
    private static final Device MINION_2_INTG_DEVICE = createDevice(2);
    private static final Device MINION_3_INTG_DEVICE = createDevice(3);

    private static final K8sNode MINION_1 = createNode(
            MINION_1_HOSTNAME,
            MINION,
            MINION_1_INTG_DEVICE,
            IpAddress.valueOf("10.100.0.1"),
            INIT
    );
    private static final K8sNode MINION_2 = createNode(
            MINION_2_HOSTNAME,
            MINION,
            MINION_2_INTG_DEVICE,
            IpAddress.valueOf("10.100.0.2"),
            INIT
    );
    private static final K8sNode MINION_3 = createNode(
            MINION_3_HOSTNAME,
            MINION,
            MINION_3_INTG_DEVICE,
            IpAddress.valueOf("10.100.0.3"),
            COMPLETE
    );

    private final TestK8sNodeListener testListener = new TestK8sNodeListener();

    private K8sNodeManager target;
    private DistributedK8sNodeStore nodeStore;

    /**
     * Initial setup for this unit test.
     */
    @Before
    public void setUp() {
        nodeStore = new DistributedK8sNodeStore();
        TestUtils.setField(nodeStore, "coreService", new TestCoreService());
        TestUtils.setField(nodeStore, "storageService", new TestStorageService());
        TestUtils.setField(nodeStore, "eventExecutor", MoreExecutors.newDirectExecutorService());
        nodeStore.activate();

        nodeStore.createNode(MINION_2);
        nodeStore.createNode(MINION_3);

        target = new K8sNodeManager();
        target.storageService = new TestStorageService();
        target.coreService = new TestCoreService();
        target.clusterService = new TestClusterService();
        target.leadershipService = new TestLeadershipService();
        target.nodeStore = nodeStore;
        target.addListener(testListener);
        target.activate();
        testListener.events.clear();
    }

    /**
     * Clean up unit test.
     */
    @After
    public void tearDown() {
        target.removeListener(testListener);
        target.deactivate();
        nodeStore.deactivate();
        nodeStore = null;
        target = null;
    }

    /**
     * Checks if creating and removing a node work well with proper events.
     */
    @Test
    public void testCreateAndRemoveNode() {
        target.createNode(MINION_1);
        assertEquals(ERR_SIZE, 3, target.nodes().size());
        assertNotNull(target.node(MINION_1_HOSTNAME));

        target.removeNode(MINION_1_HOSTNAME);
        assertEquals(ERR_SIZE, 2, target.nodes().size());
        assertNull(target.node(MINION_1_HOSTNAME));

        validateEvents(K8S_NODE_CREATED, K8S_NODE_REMOVED);
    }

    /**
     * Checks if creating null node fails with proper exception.
     */
    @Test(expected = NullPointerException.class)
    public void testCreateNullNode() {
        target.createNode(null);
    }

    /**
     * Checks if creating a duplicated node fails with proper exception.
     */
    @Test(expected = IllegalArgumentException.class)
    public void testCreateDuplicateNode() {
        target.createNode(MINION_1);
        target.createNode(MINION_1);
    }

    /**
     * Checks if removing null node fails with proper exception.
     */
    @Test(expected = IllegalArgumentException.class)
    public void testRemoveNullNode() {
        target.removeNode(null);
    }

    /**
     * Checks if updating a node works well with proper event.
     */
    @Test
    public void testUpdateNode() {
        K8sNode updated = DefaultK8sNode.from(MINION_2)
                .dataIp(IpAddress.valueOf("10.200.0.100"))
                .build();
        target.updateNode(updated);
        assertEquals(ERR_NOT_MATCH, updated, target.node(MINION_2_INTG_DEVICE.id()));
        validateEvents(K8S_NODE_UPDATED);
    }

    /**
     * Checks if updating a node state to complete generates proper events.
     */
    @Test
    public void testUpdateNodeStateComplete() {
        K8sNode updated = DefaultK8sNode.from(MINION_2)
                .state(COMPLETE)
                .build();
        target.updateNode(updated);
        assertEquals(ERR_NOT_MATCH, updated, target.node(MINION_2_HOSTNAME));
        validateEvents(K8S_NODE_UPDATED, K8S_NODE_COMPLETE);
    }

    /**
     * Checks if updating a node state to incomplete generates proper events.
     */
    @Test
    public void testUpdateNodeStateIncomplete() {
        K8sNode updated = DefaultK8sNode.from(MINION_3)
                .state(INCOMPLETE)
                .build();
        target.updateNode(updated);
        assertEquals(ERR_NOT_MATCH, updated, target.node(MINION_3_HOSTNAME));
        validateEvents(K8S_NODE_UPDATED, K8S_NODE_INCOMPLETE);
    }

    /**
     * Checks if updating a null node fails with proper exception.
     */
    @Test(expected = NullPointerException.class)
    public void testUpdateNullNode() {
        target.updateNode(null);
    }

    /**
     * Checks if updating not existing node fails with proper exception.
     */
    @Test(expected = IllegalArgumentException.class)
    public void testUpdateNotExistingNode() {
        target.updateNode(MINION_1);
    }

    /**
     * Checks if getting all nodes method returns correct set of nodes.
     */
    @Test
    public void testGetAllNodes() {
        assertEquals(ERR_SIZE, 2, target.nodes().size());
        assertTrue(ERR_NOT_FOUND, target.nodes().contains(MINION_2));
        assertTrue(ERR_NOT_FOUND, target.nodes().contains(MINION_3));
    }

    /**
     * Checks if getting complete nodes method returns correct set of nodes.
     */
    @Test
    public void testGetCompleteNodes() {
        assertEquals(ERR_SIZE, 1, target.completeNodes().size());
        assertTrue(ERR_NOT_FOUND, target.completeNodes().contains(MINION_3));
    }

    /**
     * Checks if getting nodes by type method returns correct set of nodes.
     */
    @Test
    public void testGetNodesByType() {
        assertEquals(ERR_SIZE, 2, target.nodes(MINION).size());
        assertTrue(ERR_NOT_FOUND, target.nodes(MINION).contains(MINION_2));
        assertTrue(ERR_NOT_FOUND, target.nodes(MINION).contains(MINION_3));
    }

    /**
     * Checks if getting a node by hostname returns correct node.
     */
    @Test
    public void testGetNodeByHostname() {
        assertEquals(ERR_NOT_FOUND, target.node(MINION_2_HOSTNAME), MINION_2);
        assertEquals(ERR_NOT_FOUND, target.node(MINION_3_HOSTNAME), MINION_3);
    }

    private void validateEvents(Enum... types) {
        int i = 0;
        assertEquals("Number of events did not match", types.length, testListener.events.size());
        for (Event event : testListener.events) {
            assertEquals("Incorrect event received", types[i], event.type());
            i++;
        }
        testListener.events.clear();
    }

    private static Device createDevice(long devIdNum) {
        return new DefaultDevice(new ProviderId("of", "foo"),
                DeviceId.deviceId(String.format("of:%016d", devIdNum)),
                SWITCH,
                "manufacturer",
                "hwVersion",
                "swVersion",
                "serialNumber",
                new ChassisId(1));
    }

    private static class TestK8sNodeListener implements K8sNodeListener {
        private List<K8sNodeEvent> events = Lists.newArrayList();

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

    private static class TestCoreService extends CoreServiceAdapter {
        @Override
        public ApplicationId registerApplication(String name) {
            return TEST_APP_ID;
        }
    }

    private class TestClusterService extends ClusterServiceAdapter {

    }

    private static class TestLeadershipService extends LeadershipServiceAdapter {

    }

    private static K8sNode createNode(String hostname, K8sNode.Type type,
                                      Device intgBridge, IpAddress ipAddr,
                                      K8sNodeState state) {
        return DefaultK8sNode.builder()
                .hostname(hostname)
                .type(type)
                .intgBridge(intgBridge.id())
                .managementIp(ipAddr)
                .dataIp(ipAddr)
                .state(state)
                .build();
    }
}
