/*
 * Copyright 2016-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.ui.impl.topo.model;

import org.junit.Before;
import org.junit.Test;
import org.onosproject.event.Event;
import org.onosproject.event.EventDispatcher;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.region.Region;
import org.onosproject.ui.model.topo.UiModelEvent.Type;
import org.onosproject.ui.model.topo.UiClusterMember;
import org.onosproject.ui.model.topo.UiDevice;
import org.onosproject.ui.model.topo.UiDeviceLink;
import org.onosproject.ui.model.topo.UiElement;
import org.onosproject.ui.model.topo.UiHost;
import org.onosproject.ui.model.topo.UiLinkId;
import org.onosproject.ui.model.topo.UiRegion;

import java.util.Collection;
import java.util.Iterator;

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.cluster.NodeId.nodeId;
import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.ui.model.topo.UiLinkId.uiLinkId;

/**
 * Unit tests for {@link ModelCache}.
 */
public class ModelCacheTest extends AbstractTopoModelTest {

    private class TestEvDisp implements EventDispatcher {

        private Event<Type, UiElement> lastEvent = null;
        private int eventCount = 0;

        @Override
        public void post(Event event) {
            lastEvent = event;
            eventCount++;
//            print("Event dispatched: %s", event);
        }

        private void assertEventCount(int exp) {
            assertEquals("unex event count", exp, eventCount);
        }

        private void assertLast(Type expEventType, String expId) {
            assertNotNull("no last event", lastEvent);
            assertEquals("unex event type", expEventType, lastEvent.type());
            assertEquals("unex element ID", expId, lastEvent.subject().idAsString());
        }
    }


    private final TestEvDisp dispatcher = new TestEvDisp();

    private ModelCache cache;

    private void assertContains(String msg, Collection<?> coll, Object... things) {
        for (Object o : things) {
            assertTrue(msg, coll.contains(o));
        }
    }

    @Before
    public void setUp() {
        cache = new ModelCache(MOCK_SERVICES, dispatcher);
    }

    @Test
    public void basic() {
        title("basic");
        print(cache);
        assertEquals("unex # members", 0, cache.clusterMemberCount());
        assertEquals("unex # regions", 0, cache.regionCount());
    }

    @Test
    public void addAndRemoveClusterMember() {
        title("addAndRemoveClusterMember");
        print(cache);
        assertEquals("unex # members", 0, cache.clusterMemberCount());
        dispatcher.assertEventCount(0);

        cache.addOrUpdateClusterMember(CNODE_1);
        print(cache);
        assertEquals("unex # members", 1, cache.clusterMemberCount());
        dispatcher.assertEventCount(1);
        dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);

        cache.removeClusterMember(CNODE_1);
        print(cache);
        assertEquals("unex # members", 0, cache.clusterMemberCount());
        dispatcher.assertEventCount(2);
        dispatcher.assertLast(Type.CLUSTER_MEMBER_REMOVED, C1);
    }

    @Test
    public void nonExistentClusterMember() {
        title("nonExistentClusterMember");
        cache.addOrUpdateClusterMember(CNODE_1);
        print(cache);
        assertEquals("unex # members", 1, cache.clusterMemberCount());
        dispatcher.assertEventCount(1);
        dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);

        cache.removeClusterMember(CNODE_2);
        assertEquals("unex # members", 1, cache.clusterMemberCount());
        dispatcher.assertEventCount(1);
    }

    @Test
    public void createThreeNodeCluster() {
        title("createThreeNodeCluster");
        cache.addOrUpdateClusterMember(CNODE_1);
        dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
        cache.addOrUpdateClusterMember(CNODE_2);
        dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C2);
        cache.addOrUpdateClusterMember(CNODE_3);
        dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C3);
        dispatcher.assertEventCount(3);
        print(cache);
    }

    @Test
    public void addNodeThenExamineIt() {
        title("addNodeThenExamineIt");
        cache.addOrUpdateClusterMember(CNODE_1);
        dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);

        UiClusterMember member = cache.accessClusterMember(nodeId(C1));
        print(member);
        // see AbstractUiImplTest Mock Environment for expected values...
        assertEquals("wrong id str", C1, member.idAsString());
        assertEquals("wrong id", nodeId(C1), member.id());
        assertEquals("not online", true, member.isOnline());
        assertEquals("not ready", true, member.isReady());
    }


    @Test
    public void addNodeAndDevices() {
        title("addNodeAndDevices");
        cache.addOrUpdateClusterMember(CNODE_1);
        dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
        cache.addOrUpdateDevice(DEV_1);
        dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D1);
        cache.addOrUpdateDevice(DEV_2);
        dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D2);
        cache.addOrUpdateDevice(DEV_3);
        dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D3);
        dispatcher.assertEventCount(4);
        print(cache);

        assertEquals("unex # nodes", 1, cache.clusterMemberCount());
        assertEquals("unex # devices", 3, cache.deviceCount());
        cache.removeDevice(DEV_4);
        assertEquals("unex # devices", 3, cache.deviceCount());
        dispatcher.assertEventCount(4);

        cache.removeDevice(DEV_2);
        dispatcher.assertLast(Type.DEVICE_REMOVED, D2);
        dispatcher.assertEventCount(5);

        // check out details of device
        UiDevice dev = cache.accessDevice(DEVID_1);
        assertEquals("wrong id", D1, dev.idAsString());
        assertEquals("wrong region", R1, dev.regionId().toString());
        Device d = dev.backingDevice();
        assertEquals("wrong serial", SERIAL, d.serialNumber());
    }

    @Test
    public void addRegions() {
        title("addRegions");
        cache.addOrUpdateRegion(REGION_1);
        dispatcher.assertLast(Type.REGION_ADDED_OR_UPDATED, R1);
        dispatcher.assertEventCount(1);
        assertEquals("unex # regions", 1, cache.regionCount());

        cache.addOrUpdateRegion(REGION_2);
        dispatcher.assertLast(Type.REGION_ADDED_OR_UPDATED, R2);
        dispatcher.assertEventCount(2);
        assertEquals("unex # regions", 2, cache.regionCount());

        print(cache);

        cache.removeRegion(REGION_3);
        dispatcher.assertEventCount(2);
        assertEquals("unex # regions", 2, cache.regionCount());

        cache.removeRegion(REGION_1);
        dispatcher.assertLast(Type.REGION_REMOVED, R1);
        dispatcher.assertEventCount(3);
        assertEquals("unex # regions", 1, cache.regionCount());

        print(cache);

        UiRegion region = cache.accessRegion(REGION_2.id());
        assertEquals("wrong id", REGION_2.id(), region.id());
        assertEquals("unex # device IDs", 3, region.deviceIds().size());
        assertContains("missing ID", region.deviceIds(), DEVID_4, DEVID_5, DEVID_6);
        Region r = region.backingRegion();
        print(r);
        assertEquals("wrong region name", "Region-R2", r.name());
    }

    private static final String[] LINKS_2_7 = {D2, "27", D7, "72"};

    @Test
    public void addLinks() {
        title("addLinks");

        Iterator<Link> iter = makeLinkPair(LINKS_2_7).iterator();
        Link link1 = iter.next();
        Link link2 = iter.next();
        print(link1);
        print(link2);

        UiLinkId idA2B = uiLinkId(link1);
        UiLinkId idB2A = uiLinkId(link2);
        // remember, link IDs are canonicalized
        assertEquals("not same link ID", idA2B, idB2A);

        // we've established that the ID is the same for both
        UiLinkId linkId = idA2B;

        cache.addOrUpdateDeviceLink(link1);
        dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
        dispatcher.assertEventCount(1);
        assertEquals("unex # links", 1, cache.deviceLinkCount());

        UiDeviceLink link = cache.accessDeviceLink(linkId);
        assertEquals("dev A not d2", DEVID_2, link.deviceA());
        assertEquals("dev B not d7", DEVID_7, link.deviceB());
        assertEquals("wrong backing link A-B", link1, link.linkAtoB());
        assertEquals("backing link B-A?", null, link.linkBtoA());

        cache.addOrUpdateDeviceLink(link2);
        dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
        dispatcher.assertEventCount(2);
        // NOTE: yes! expect 1 UiLink
        assertEquals("unex # links", 1, cache.deviceLinkCount());

        link = cache.accessDeviceLink(linkId);
        assertEquals("dev A not d2", DEVID_2, link.deviceA());
        assertEquals("dev B not d7", DEVID_7, link.deviceB());
        assertEquals("wrong backing link A-B", link1, link.linkAtoB());
        assertEquals("wrong backing link B-A", link2, link.linkBtoA());

        // now remove links one at a time
        cache.removeDeviceLink(link1);
        // NOTE: yes! ADD_OR_UPDATE, since the link was updated
        dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
        dispatcher.assertEventCount(3);
        // NOTE: yes! expect 1 UiLink (still)
        assertEquals("unex # links", 1, cache.deviceLinkCount());

        link = cache.accessDeviceLink(linkId);
        assertEquals("dev A not d2", DEVID_2, link.deviceA());
        assertEquals("dev B not d7", DEVID_7, link.deviceB());
        assertEquals("backing link A-B?", null, link.linkAtoB());
        assertEquals("wrong backing link B-A", link2, link.linkBtoA());

        // remove final link
        cache.removeDeviceLink(link2);
        dispatcher.assertLast(Type.LINK_REMOVED, linkId.toString());
        dispatcher.assertEventCount(4);
        // NOTE: finally link should be removed from cache
        assertEquals("unex # links", 0, cache.deviceLinkCount());
    }

    private void assertHostLinkCounts(int nHosts, int nLinks) {
        assertEquals("unex # hosts", nHosts, cache.hostCount());
        assertEquals("unex # links", nLinks, cache.edgeLinkCount());
    }

    private void assertLocation(HostId hid, DeviceId expDev, int expPort) {
        UiHost h = cache.accessHost(hid);
        assertEquals("unex device", expDev, h.locationDevice());
        assertEquals("unex port", portNumber(expPort), h.locationPort());
    }

    @Test
    public void addHosts() {
        title("addHosts");

        assertHostLinkCounts(0, 0);
        Host hostA = createHost(DEV_1, 101, "a");
        Host hostB = createHost(DEV_1, 102, "b");

        // add a host
        cache.addOrUpdateHost(hostA);
        dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostA.id().toString());
        dispatcher.assertEventCount(1);
        assertHostLinkCounts(1, 1);
        assertLocation(hostA.id(), DEVID_1, 101);

        // add a second host
        cache.addOrUpdateHost(hostB);
        dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostB.id().toString());
        dispatcher.assertEventCount(2);
        assertHostLinkCounts(2, 2);
        assertLocation(hostB.id(), DEVID_1, 102);

        // update the first host
        cache.addOrUpdateHost(hostA);
        dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostA.id().toString());
        dispatcher.assertEventCount(3);
        assertHostLinkCounts(2, 2);
        assertLocation(hostA.id(), DEVID_1, 101);

        print(cache.dumpString());

        // remove the second host
        cache.removeHost(hostB);
        dispatcher.assertLast(Type.HOST_REMOVED, hostB.id().toString());
        dispatcher.assertEventCount(4);
        assertHostLinkCounts(1, 1);
        assertNull("still host B?", cache.accessHost(hostB.id()));

        print(cache.dumpString());

        // first, verify where host A is currently residing
        assertLocation(hostA.id(), DEVID_1, 101);

        // now let's move hostA to a different port
        Host movedHost = createHost(DEV_1, 200, "a");
        print(hostA);
        print(movedHost);

        cache.moveHost(movedHost, hostA);
        dispatcher.assertLast(Type.HOST_MOVED, hostA.id().toString());
        dispatcher.assertEventCount(5);
        assertHostLinkCounts(1, 1);

        assertLocation(hostA.id(), DEVID_1, 200);

        print(cache.dumpString());

        // finally, let's move the host to a different device and port
        Host movedAgain = createHost(DEV_8, 800, "a");

        cache.moveHost(movedAgain, movedHost);
        dispatcher.assertLast(Type.HOST_MOVED, hostA.id().toString());
        dispatcher.assertEventCount(6);
        assertHostLinkCounts(1, 1);

        assertLocation(hostA.id(), DEVID_8, 800);

        print(cache.dumpString());
    }


    @Test
    public void load() {
        title("load");
        cache.load();
        print(cache.dumpString());

        // See mock service bundle for expected values (AbstractTopoModelTest)
        assertEquals("unex # cnodes", 3, cache.clusterMemberCount());
        assertEquals("unex # regions", 3, cache.regionCount());
        assertEquals("unex # devices", 9, cache.deviceCount());
        assertEquals("unex # hosts", 18, cache.hostCount());
        assertEquals("unex # device-links", 8, cache.deviceLinkCount());
        assertEquals("unex # edge-links", 18, cache.edgeLinkCount());
        assertEquals("unex # synth-links", 0, cache.synthLinkCount());
    }
}
