/*
 * Copyright 2014-present 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.cluster.impl;

import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.packet.IpAddress;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.mastership.MastershipService;
import org.onosproject.mastership.MastershipStore;
import org.onosproject.mastership.MastershipTermService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionId;
import org.onosproject.net.region.RegionStore;
import org.onosproject.net.region.impl.RegionManager;
import org.onosproject.store.cluster.StaticClusterService;
import org.onosproject.store.region.impl.DistributedRegionStore;
import org.onosproject.store.service.TestStorageService;
import org.onosproject.store.trivial.SimpleMastershipStore;

import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.*;
import static org.onosproject.net.MastershipRole.MASTER;
import static org.onosproject.net.MastershipRole.NONE;
import static org.onosproject.net.MastershipRole.STANDBY;
import static org.onosproject.net.NetTestTools.injectEventDispatcher;
import static org.onosproject.net.region.Region.Type.METRO;

/**
 * Test codifying the mastership service contracts.
 */
public class MastershipManagerTest {

    private static final NodeId NID_LOCAL = new NodeId("local");
    private static final NodeId NID_OTHER = new NodeId("foo");
    private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1");
    private static final DeviceId DEV_MASTER = DeviceId.deviceId("of:1");
    private static final DeviceId DEV_OTHER = DeviceId.deviceId("of:2");

    private static final RegionId RID1 = RegionId.regionId("r1");
    private static final RegionId RID2 = RegionId.regionId("r2");
    private static final DeviceId DID1 = DeviceId.deviceId("foo:d1");
    private static final DeviceId DID2 = DeviceId.deviceId("foo:d2");
    private static final DeviceId DID3 = DeviceId.deviceId("foo:d3");
    private static final NodeId NID1 = NodeId.nodeId("n1");
    private static final NodeId NID2 = NodeId.nodeId("n2");
    private static final NodeId NID3 = NodeId.nodeId("n3");
    private static final NodeId NID4 = NodeId.nodeId("n4");
    private static final ControllerNode CNODE1 =
            new DefaultControllerNode(NID1, IpAddress.valueOf("127.0.1.1"));
    private static final ControllerNode CNODE2 =
            new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.1.2"));
    private static final ControllerNode CNODE3 =
            new DefaultControllerNode(NID3, IpAddress.valueOf("127.0.1.3"));
    private static final ControllerNode CNODE4 =
            new DefaultControllerNode(NID4, IpAddress.valueOf("127.0.1.4"));


    private MastershipManager mgr;
    protected MastershipService service;
    private TestRegionManager regionManager;
    private RegionStore regionStore;
    private TestClusterService testClusterService;

    @Before
    public void setUp() throws Exception {
        mgr = new MastershipManager();
        service = mgr;
        injectEventDispatcher(mgr, new TestEventDispatcher());
        testClusterService = new TestClusterService();
        mgr.clusterService = testClusterService;
        mgr.store = new TestSimpleMastershipStore(mgr.clusterService);
        regionStore = new DistributedRegionStore();
        TestUtils.setField(regionStore, "storageService", new TestStorageService());
        TestUtils.callMethod(regionStore, "activate",
                             new Class<?>[] {});
        regionManager = new TestRegionManager();
        TestUtils.setField(regionManager, "store", regionStore);
        regionManager.activate();
        mgr.regionService = regionManager;

        ComponentConfigService mockConfigService =
                EasyMock.createMock(ComponentConfigService.class);
        expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
        mockConfigService.registerProperties(mgr.getClass());
        expectLastCall();
        mockConfigService.unregisterProperties(mgr.getClass(), false);
        expectLastCall();
        expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
        mgr.cfgService = mockConfigService;
        replay(mockConfigService);

        mgr.activate();
    }

    @After
    public void tearDown() {
        mgr.deactivate();
        mgr.clusterService = null;
        injectEventDispatcher(mgr, null);
        regionManager.deactivate();
        mgr.regionService = null;
        mgr.store = null;
    }

    @Test
    public void setRole() {
        mgr.setRole(NID_OTHER, DEV_MASTER, MASTER);
        assertEquals("wrong local role:", NONE, mgr.getLocalRole(DEV_MASTER));
        assertEquals("wrong obtained role:", STANDBY, Futures.getUnchecked(mgr.requestRoleFor(DEV_MASTER)));

        //set to master
        mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
        assertEquals("wrong local role:", MASTER, mgr.getLocalRole(DEV_MASTER));
    }

    @Test
    public void relinquishMastership() {
        //no backups - should just turn to NONE for device.
        mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
        assertEquals("wrong role:", MASTER, mgr.getLocalRole(DEV_MASTER));
        mgr.relinquishMastership(DEV_MASTER);
        assertNull("wrong master:", mgr.getMasterFor(DEV_OTHER));
        assertEquals("wrong role:", NONE, mgr.getLocalRole(DEV_MASTER));

        //not master, nothing should happen
        mgr.setRole(NID_LOCAL, DEV_OTHER, NONE);
        mgr.relinquishMastership(DEV_OTHER);
        assertNull("wrong role:", mgr.getMasterFor(DEV_OTHER));

        //provide NID_OTHER as backup and relinquish
        mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
        assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_MASTER));
        mgr.setRole(NID_OTHER, DEV_MASTER, STANDBY);
        mgr.relinquishMastership(DEV_MASTER);
        assertEquals("wrong master:", NID_OTHER, mgr.getMasterFor(DEV_MASTER));
    }

    @Test
    public void requestRoleFor() {
        mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
        mgr.setRole(NID_OTHER, DEV_OTHER, MASTER);

        //local should be master for one but standby for other
        assertEquals("wrong role:", MASTER, Futures.getUnchecked(mgr.requestRoleFor(DEV_MASTER)));
        assertEquals("wrong role:", STANDBY, Futures.getUnchecked(mgr.requestRoleFor(DEV_OTHER)));
    }

    @Test
    public void getMasterFor() {
        mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
        mgr.setRole(NID_OTHER, DEV_OTHER, MASTER);
        assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_MASTER));
        assertEquals("wrong master:", NID_OTHER, mgr.getMasterFor(DEV_OTHER));

        //have NID_OTHER hand over DEV_OTHER to NID_LOCAL
        mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER);
        assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_OTHER));
    }

    @Test
    public void getDevicesOf() {
        mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
        mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY);
        assertEquals("should be one device:", 1, mgr.getDevicesOf(NID_LOCAL).size());
        //hand both devices to NID_LOCAL
        mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER);
        assertEquals("should be two devices:", 2, mgr.getDevicesOf(NID_LOCAL).size());
    }

    @Test
    public void termService() {
        MastershipTermService ts = mgr;

        //term = 1 for both
        mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
        assertEquals("inconsistent term: ", 1, ts.getMastershipTerm(DEV_MASTER).termNumber());

        //hand devices to NID_LOCAL and back: term = 1 + 2
        mgr.setRole(NID_OTHER, DEV_MASTER, MASTER);
        mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
        assertEquals("inconsistent terms: ", 3, ts.getMastershipTerm(DEV_MASTER).termNumber());
    }

    @Test
    public void balanceWithRegion1() {
        //set up region - 2 sets of masters with 1 node in each
        Set<NodeId> masterSet1 = ImmutableSet.of(NID1);
        Set<NodeId> masterSet2 = ImmutableSet.of(NID2);
        List<Set<NodeId>> masters = ImmutableList.of(masterSet1, masterSet2);
        Region r = regionManager.createRegion(RID1, "R1", METRO, masters);
        regionManager.addDevices(RID1, ImmutableSet.of(DID1, DID2));
        Set<DeviceId> deviceIds = regionManager.getRegionDevices(RID1);
        assertEquals("incorrect device count", 2, deviceIds.size());

        testClusterService.put(CNODE1, ControllerNode.State.ACTIVE);
        testClusterService.put(CNODE2, ControllerNode.State.ACTIVE);

        //set master to non region nodes
        mgr.setRole(NID_LOCAL, DID1, MASTER);
        mgr.setRole(NID_LOCAL, DID2, MASTER);
        assertEquals("wrong local role:", MASTER, mgr.getLocalRole(DID1));
        assertEquals("wrong local role:", MASTER, mgr.getLocalRole(DID2));
        assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DID1));
        assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DID2));

        //do region balancing
        mgr.useRegionForBalanceRoles = true;
        mgr.balanceRoles();
        assertEquals("wrong master:", NID1, mgr.getMasterFor(DID1));
        assertEquals("wrong master:", NID1, mgr.getMasterFor(DID2));

        // make N1 inactive
        testClusterService.put(CNODE1, ControllerNode.State.INACTIVE);
        mgr.balanceRoles();
        assertEquals("wrong master:", NID2, mgr.getMasterFor(DID1));
        assertEquals("wrong master:", NID2, mgr.getMasterFor(DID2));

    }

    @Test
    public void balanceWithRegion2() {
        //set up region - 2 sets of masters with (3 nodes, 1 node)
        Set<NodeId> masterSet1 = ImmutableSet.of(NID1, NID3, NID4);
        Set<NodeId> masterSet2 = ImmutableSet.of(NID2);
        List<Set<NodeId>> masters = ImmutableList.of(masterSet1, masterSet2);
        Region r = regionManager.createRegion(RID1, "R1", METRO, masters);
        Set<DeviceId> deviceIdsOrig = ImmutableSet.of(DID1, DID2, DID3, DEV_OTHER);
        regionManager.addDevices(RID1, deviceIdsOrig);
        Set<DeviceId> deviceIds = regionManager.getRegionDevices(RID1);
        assertEquals("incorrect device count", deviceIdsOrig.size(), deviceIds.size());
        assertEquals("incorrect devices in region", deviceIdsOrig, deviceIds);

        testClusterService.put(CNODE1, ControllerNode.State.ACTIVE);
        testClusterService.put(CNODE2, ControllerNode.State.ACTIVE);
        testClusterService.put(CNODE3, ControllerNode.State.ACTIVE);
        testClusterService.put(CNODE4, ControllerNode.State.ACTIVE);

        //set master to non region nodes
        deviceIdsOrig.forEach(deviceId1 -> mgr.setRole(NID_LOCAL, deviceId1, MASTER));
        checkDeviceMasters(deviceIds, Sets.newHashSet(NID_LOCAL), deviceId ->
                assertEquals("wrong local role:", MASTER, mgr.getLocalRole(deviceId)));

        //do region balancing
        mgr.useRegionForBalanceRoles = true;
        mgr.balanceRoles();
        Set<NodeId> expectedMasters = Sets.newHashSet(NID1, NID3, NID4);
        checkDeviceMasters(deviceIds, expectedMasters);

        // make N1 inactive
        testClusterService.put(CNODE1, ControllerNode.State.INACTIVE);
        expectedMasters.remove(NID1);
        mgr.balanceRoles();
        checkDeviceMasters(deviceIds, expectedMasters);

        // make N4 inactive
        testClusterService.put(CNODE4, ControllerNode.State.INACTIVE);
        expectedMasters.remove(NID4);
        mgr.balanceRoles();
        checkDeviceMasters(deviceIds, expectedMasters);

        // make N3 inactive
        testClusterService.put(CNODE3, ControllerNode.State.INACTIVE);
        expectedMasters = Sets.newHashSet(NID2);
        mgr.balanceRoles();
        checkDeviceMasters(deviceIds, expectedMasters);

        // make N3 active
        testClusterService.put(CNODE3, ControllerNode.State.ACTIVE);
        expectedMasters = Sets.newHashSet(NID3);
        mgr.balanceRoles();
        checkDeviceMasters(deviceIds, expectedMasters);

        // make N4 active
        testClusterService.put(CNODE4, ControllerNode.State.ACTIVE);
        expectedMasters.add(NID4);
        mgr.balanceRoles();
        checkDeviceMasters(deviceIds, expectedMasters);

        // make N1 active
        testClusterService.put(CNODE1, ControllerNode.State.ACTIVE);
        expectedMasters.add(NID1);
        mgr.balanceRoles();
        checkDeviceMasters(deviceIds, expectedMasters);
    }

    private void checkDeviceMasters(Set<DeviceId> deviceIds, Set<NodeId> expectedMasters) {
        checkDeviceMasters(deviceIds, expectedMasters, null);
    }

    private void checkDeviceMasters(Set<DeviceId> deviceIds, Set<NodeId> expectedMasters,
                                     Consumer<DeviceId> checkRole) {
        // each device's master must be contained in the list of expectedMasters
        deviceIds.forEach(deviceId -> {
            assertTrue("wrong master:", expectedMasters.contains(mgr.getMasterFor(deviceId)));
            if (checkRole != null) {
                checkRole.accept(deviceId);
            }
        });
        // each node in expectedMasters must have approximately the same number of devices
        if (expectedMasters.size() > 1) {
            int minValue = Integer.MAX_VALUE;
            int maxDevices = -1;
            for (NodeId nodeId: expectedMasters) {
                int numDevicesManagedByNode = mgr.getDevicesOf(nodeId).size();
                if (numDevicesManagedByNode < minValue) {
                    minValue = numDevicesManagedByNode;
                }
                if (numDevicesManagedByNode > maxDevices) {
                    maxDevices = numDevicesManagedByNode;
                }
                assertTrue("not balanced:", maxDevices - minValue <= 1);
            }
        }
    }

    private final class TestClusterService extends StaticClusterService {

        ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST);

        @Override
        public ControllerNode getLocalNode() {
            return local;
        }

        public void put(ControllerNode cn, ControllerNode.State state) {
            nodes.put(cn.id(), cn);
            nodeStates.put(cn.id(), state);
        }
    }

    private final class TestSimpleMastershipStore extends SimpleMastershipStore
            implements MastershipStore {

        public TestSimpleMastershipStore(ClusterService clusterService) {
            super.clusterService = clusterService;
        }
    }

    private class TestRegionManager extends RegionManager {
        TestRegionManager() {
            eventDispatcher = new TestEventDispatcher();
            networkConfigService = new NetworkConfigServiceAdapter();
        }
    }
}
