/*
 * 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.store.region.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.cluster.NodeId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionEvent;
import org.onosproject.net.region.RegionId;
import org.onosproject.store.service.TestStorageService;

import java.util.List;
import java.util.Set;

import static org.junit.Assert.*;
import static org.onosproject.net.region.Region.Type.*;
import static org.onosproject.net.region.RegionEvent.Type.*;

/**
 * Test of the distributed region store implementation.
 */
public class DistributedRegionStoreTest {

    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 List<Set<NodeId>> MASTERS = ImmutableList.of(ImmutableSet.of(NID1));

    private TestStore store;
    private RegionEvent event;

    /**
     * Sets up the device key store and the storage service test harness.
     */
    @Before
    public void setUp() {
        store = new TestStore();
        store.storageService = new TestStorageService();
        store.setDelegate(e -> this.event = e);
        store.activate();
    }

    /**
     * Tears down the device key store.
     */
    @After
    public void tearDown() {
        store.deactivate();
    }

    @Test
    public void basics() {
        Region r1 = store.createRegion(RID1, "R1", METRO, MASTERS);
        assertEquals("incorrect id", RID1, r1.id());
        assertEquals("incorrect event", REGION_ADDED, event.type());

        Region r2 = store.createRegion(RID2, "R2", CAMPUS, MASTERS);
        assertEquals("incorrect id", RID2, r2.id());
        assertEquals("incorrect type", CAMPUS, r2.type());
        assertEquals("incorrect event", REGION_ADDED, event.type());

        r2 = store.updateRegion(RID2, "R2", COUNTRY, MASTERS);
        assertEquals("incorrect type", COUNTRY, r2.type());
        assertEquals("incorrect event", REGION_UPDATED, event.type());

        Set<Region> regions = store.getRegions();
        assertEquals("incorrect size", 2, regions.size());
        assertTrue("missing r1", regions.contains(r1));
        assertTrue("missing r2", regions.contains(r2));

        r1 = store.getRegion(RID1);
        assertEquals("incorrect id", RID1, r1.id());

        store.removeRegion(RID1);
        regions = store.getRegions();
        assertEquals("incorrect size", 1, regions.size());
        assertTrue("missing r2", regions.contains(r2));
        assertEquals("incorrect event", REGION_REMOVED, event.type());
    }

    @Test(expected = IllegalArgumentException.class)
    public void duplicateCreate() {
        store.createRegion(RID1, "R1", METRO, MASTERS);
        store.createRegion(RID1, "R2", CAMPUS, MASTERS);
    }

    @Test(expected = ItemNotFoundException.class)
    public void missingUpdate() {
        store.updateRegion(RID1, "R1", METRO, MASTERS);
    }

    @Test
    public void membership() {
        Region r = store.createRegion(RID1, "R1", METRO, MASTERS);
        assertTrue("no devices expected", store.getRegionDevices(RID1).isEmpty());
        assertNull("no region expected", store.getRegionForDevice(DID1));

        store.addDevices(RID1, ImmutableSet.of(DID1, DID2));
        Set<DeviceId> deviceIds = store.getRegionDevices(RID1);
        assertEquals("incorrect device count", 2, deviceIds.size());
        assertTrue("missing d1", deviceIds.contains(DID1));
        assertTrue("missing d2", deviceIds.contains(DID2));
        assertEquals("wrong region", r, store.getRegionForDevice(DID1));

        store.addDevices(RID1, ImmutableSet.of(DID3));
        deviceIds = store.getRegionDevices(RID1);
        assertEquals("incorrect device count", 3, deviceIds.size());
        assertTrue("missing d3", deviceIds.contains(DID3));

        store.addDevices(RID1, ImmutableSet.of(DID3, DID1));
        deviceIds = store.getRegionDevices(RID1);
        assertEquals("incorrect device count", 3, deviceIds.size());

        // Test adding DID3 to RID2 but it is already in RID1.
        // DID3 will be removed from RID1 and added to RID2.
        Region r2 = store.createRegion(RID2, "R2", CAMPUS, MASTERS);
        store.addDevices(RID2, ImmutableSet.of(DID3));
        deviceIds = store.getRegionDevices(RID1);
        assertEquals("incorrect device count", 2, deviceIds.size());
        deviceIds = store.getRegionDevices(RID2);
        assertEquals("incorrect device count", 1, deviceIds.size());

        store.removeDevices(RID1, ImmutableSet.of(DID2, DID3));
        deviceIds = store.getRegionDevices(RID1);
        assertEquals("incorrect device count", 1, deviceIds.size());
        assertTrue("missing d1", deviceIds.contains(DID1));

        store.removeDevices(RID1, ImmutableSet.of(DID1, DID3));
        assertTrue("no devices expected", store.getRegionDevices(RID1).isEmpty());

        store.removeDevices(RID1, ImmutableSet.of(DID2));
        assertTrue("no devices expected", store.getRegionDevices(RID1).isEmpty());
    }

    class TestStore extends DistributedRegionStore {
    }
}