/*
 * Copyright 2015-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.store.trivial;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.onosproject.net.DeviceId.deviceId;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.group.DefaultGroup;
import org.onosproject.net.group.DefaultGroupBucket;
import org.onosproject.net.group.DefaultGroupDescription;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupEvent;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupOperation;
import org.onosproject.net.group.GroupStore.UpdateType;
import org.onosproject.net.group.GroupStoreDelegate;
import org.onosproject.net.group.StoredGroupBucketEntry;
import org.onosproject.net.group.StoredGroupEntry;

import com.google.common.collect.Iterables;

/**
 * Test of the simple DeviceStore implementation.
 */
public class SimpleGroupStoreTest {

    private SimpleGroupStore simpleGroupStore;
    private final ApplicationId appId =
            new DefaultApplicationId(2, "org.groupstore.test");

    public static final DeviceId D1 = deviceId("of:1");

    @Before
    public void setUp() throws Exception {
        simpleGroupStore = new SimpleGroupStore();
        simpleGroupStore.activate();
    }

    @After
    public void tearDown() throws Exception {
        simpleGroupStore.deactivate();
    }

    private class InternalGroupStoreDelegate
                implements GroupStoreDelegate {
        private GroupId createdGroupId = null;
        private GroupKey createdGroupKey;
        private GroupBuckets createdBuckets;
        private GroupEvent.Type expectedEvent;

        public InternalGroupStoreDelegate(GroupKey key,
                                          GroupBuckets buckets,
                                          GroupEvent.Type expectedEvent) {
            this.createdBuckets = buckets;
            this.createdGroupKey = key;
            this.expectedEvent = expectedEvent;
        }
        @Override
        public void notify(GroupEvent event) {
            assertEquals(expectedEvent, event.type());
            assertEquals(Group.Type.SELECT, event.subject().type());
            assertEquals(D1, event.subject().deviceId());
            assertEquals(createdGroupKey, event.subject().appCookie());
            assertEquals(createdBuckets.buckets(), event.subject().buckets().buckets());
            if (expectedEvent == GroupEvent.Type.GROUP_ADD_REQUESTED) {
                createdGroupId = event.subject().id();
                assertEquals(Group.GroupState.PENDING_ADD,
                             event.subject().state());
            } else if (expectedEvent == GroupEvent.Type.GROUP_ADDED) {
                createdGroupId = event.subject().id();
                assertEquals(Group.GroupState.ADDED,
                             event.subject().state());
            } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATED) {
                createdGroupId = event.subject().id();
                assertEquals(true,
                             event.subject().buckets().
                             buckets().containsAll(createdBuckets.buckets()));
                assertEquals(true,
                             createdBuckets.buckets().
                             containsAll(event.subject().buckets().buckets()));
                for (GroupBucket bucket:event.subject().buckets().buckets()) {
                    Optional<GroupBucket> matched = createdBuckets.buckets()
                            .stream()
                            .filter((expected) -> expected.equals(bucket))
                            .findFirst();
                    assertEquals(matched.get().packets(),
                                 bucket.packets());
                    assertEquals(matched.get().bytes(),
                                 bucket.bytes());
                }
                assertEquals(Group.GroupState.ADDED,
                             event.subject().state());
            } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATE_REQUESTED) {
                assertEquals(Group.GroupState.PENDING_UPDATE,
                             event.subject().state());
                for (GroupBucket bucket:event.subject().buckets().buckets()) {
                    Optional<GroupBucket> matched = createdBuckets.buckets()
                            .stream()
                            .filter((expected) -> expected.equals(bucket))
                            .findFirst();
                    assertEquals(matched.get().weight(),
                            bucket.weight());
                    assertEquals(matched.get().watchGroup(),
                            bucket.watchGroup());
                    assertEquals(matched.get().watchPort(),
                            bucket.watchPort());
                }
            } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVE_REQUESTED) {
                assertEquals(Group.GroupState.PENDING_DELETE,
                             event.subject().state());
            } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVED) {
                createdGroupId = event.subject().id();
                assertEquals(Group.GroupState.PENDING_DELETE,
                             event.subject().state());
            } else if (expectedEvent == GroupEvent.Type.GROUP_ADD_FAILED) {
                createdGroupId = event.subject().id();
                assertEquals(Group.GroupState.PENDING_ADD,
                        event.subject().state());
            } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATE_FAILED) {
                createdGroupId = event.subject().id();
                assertEquals(Group.GroupState.PENDING_UPDATE,
                        event.subject().state());
            } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVE_FAILED) {
                createdGroupId = event.subject().id();
                assertEquals(Group.GroupState.PENDING_DELETE,
                        event.subject().state());
            }
        }

        public void verifyGroupId(GroupId id) {
            assertEquals(createdGroupId, id);
        }
    }

    /**
     * Tests group store operations. The following operations are tested:
     * a)Tests device group audit completion status change
     * b)Tests storeGroup operation
     * c)Tests getGroupCount operation
     * d)Tests getGroup operation
     * e)Tests getGroups operation
     * f)Tests addOrUpdateGroupEntry operation from southbound
     * g)Tests updateGroupDescription for ADD operation from northbound
     * h)Tests updateGroupDescription for REMOVE operation from northbound
     * i)Tests deleteGroupDescription operation from northbound
     * j)Tests removeGroupEntry operation from southbound
     */
    @Test
    public void testGroupStoreOperations() {
        // Set the Device AUDIT completed in the store
        simpleGroupStore.deviceInitialAuditCompleted(D1, true);

        // Testing storeGroup operation
        GroupKey newKey = new DefaultGroupKey("group1".getBytes());
        testStoreAndGetGroup(newKey);

        // Testing addOrUpdateGroupEntry operation from southbound
        GroupKey currKey = newKey;
        testAddGroupEntryFromSB(currKey);

        // Testing updateGroupDescription for ADD operation from northbound
        newKey = new DefaultGroupKey("group1AddBuckets".getBytes());
        testAddBuckets(currKey, newKey);

        // Testing updateGroupDescription for REMOVE operation from northbound
        currKey = newKey;
        newKey = new DefaultGroupKey("group1RemoveBuckets".getBytes());
        testRemoveBuckets(currKey, newKey);

        // Testing addOrUpdateGroupEntry operation from southbound
        currKey = newKey;
        testUpdateGroupEntryFromSB(currKey);

        // Testing deleteGroupDescription operation from northbound
        testDeleteGroup(currKey);

        // Testing removeGroupEntry operation from southbound
        testRemoveGroupFromSB(currKey);

        // Testing removing all groups on the given device
        newKey = new DefaultGroupKey("group1".getBytes());
        testStoreAndGetGroup(newKey);
        testDeleteGroupOnDevice(newKey);
    }

    // Testing storeGroup operation
    private void testStoreAndGetGroup(GroupKey key) {
        PortNumber[] ports = {PortNumber.portNumber(31),
                              PortNumber.portNumber(32)};
        List<PortNumber> outPorts = new ArrayList<>();
        outPorts.addAll(Arrays.asList(ports));

        List<GroupBucket> buckets = new ArrayList<>();
        for (PortNumber portNumber: outPorts) {
            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
            tBuilder.setOutput(portNumber)
                    .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
                    .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                    .pushMpls()
                    .setMpls(MplsLabel.mplsLabel(106));
            buckets.add(DefaultGroupBucket.createSelectGroupBucket(
                                                        tBuilder.build()));
        }
        GroupBuckets groupBuckets = new GroupBuckets(buckets);
        GroupDescription groupDesc = new DefaultGroupDescription(
                                                 D1,
                                                 Group.Type.SELECT,
                                                 groupBuckets,
                                                 key,
                                                 null,
                                                 appId);
        InternalGroupStoreDelegate checkStoreGroupDelegate =
                new InternalGroupStoreDelegate(key,
                                               groupBuckets,
                                               GroupEvent.Type.GROUP_ADD_REQUESTED);
        simpleGroupStore.setDelegate(checkStoreGroupDelegate);
        // Testing storeGroup operation
        simpleGroupStore.storeGroupDescription(groupDesc);

        // Testing getGroupCount operation
        assertEquals(1, simpleGroupStore.getGroupCount(D1));

        // Testing getGroup operation
        Group createdGroup = simpleGroupStore.getGroup(D1, key);
        checkStoreGroupDelegate.verifyGroupId(createdGroup.id());

        // Testing getGroups operation
        Iterable<Group> createdGroups = simpleGroupStore.getGroups(D1);
        int groupCount = 0;
        for (Group group:createdGroups) {
            checkStoreGroupDelegate.verifyGroupId(group.id());
            groupCount++;
        }
        assertEquals(1, groupCount);
        simpleGroupStore.unsetDelegate(checkStoreGroupDelegate);
    }

    // Testing addOrUpdateGroupEntry operation from southbound
    private void testAddGroupEntryFromSB(GroupKey currKey) {
        Group existingGroup = simpleGroupStore.getGroup(D1, currKey);

        InternalGroupStoreDelegate addGroupEntryDelegate =
                new InternalGroupStoreDelegate(currKey,
                                               existingGroup.buckets(),
                                               GroupEvent.Type.GROUP_ADDED);
        simpleGroupStore.setDelegate(addGroupEntryDelegate);
        simpleGroupStore.addOrUpdateGroupEntry(existingGroup);
        simpleGroupStore.unsetDelegate(addGroupEntryDelegate);
    }

    // Testing addOrUpdateGroupEntry operation from southbound
    private void testUpdateGroupEntryFromSB(GroupKey currKey) {
        Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
        int totalPkts = 0;
        int totalBytes = 0;
        List<GroupBucket> newBucketList = new ArrayList<>();
        for (GroupBucket bucket:existingGroup.buckets().buckets()) {
            StoredGroupBucketEntry newBucket =
                    (StoredGroupBucketEntry)
                    DefaultGroupBucket.createSelectGroupBucket(bucket.treatment());
            newBucket.setPackets(10);
            newBucket.setBytes(10 * 256 * 8);
            totalPkts += 10;
            totalBytes += 10 * 256 * 8;
            newBucketList.add(newBucket);
        }
        GroupBuckets updatedBuckets = new GroupBuckets(newBucketList);
        Group updatedGroup = new DefaultGroup(existingGroup.id(),
                                              existingGroup.deviceId(),
                                              existingGroup.type(),
                                              updatedBuckets);
        ((StoredGroupEntry) updatedGroup).setPackets(totalPkts);
        ((StoredGroupEntry) updatedGroup).setBytes(totalBytes);

        InternalGroupStoreDelegate updateGroupEntryDelegate =
                new InternalGroupStoreDelegate(currKey,
                                               updatedBuckets,
                                               GroupEvent.Type.GROUP_UPDATED);
        simpleGroupStore.setDelegate(updateGroupEntryDelegate);
        simpleGroupStore.addOrUpdateGroupEntry(updatedGroup);
        simpleGroupStore.unsetDelegate(updateGroupEntryDelegate);
    }

    // Testing updateGroupDescription for ADD operation from northbound
    private void testAddBuckets(GroupKey currKey, GroupKey addKey) {
        Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
        List<GroupBucket> buckets = new ArrayList<>();
        buckets.addAll(existingGroup.buckets().buckets());

        PortNumber[] newNeighborPorts = {PortNumber.portNumber(41),
                                         PortNumber.portNumber(42)};
        List<PortNumber> newOutPorts = new ArrayList<>();
        newOutPorts.addAll(Collections.singletonList(newNeighborPorts[0]));

        List<GroupBucket> toAddBuckets = new ArrayList<>();
        for (PortNumber portNumber: newOutPorts) {
            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
            tBuilder.setOutput(portNumber)
                    .setEthDst(MacAddress.valueOf("00:00:00:00:00:03"))
                    .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                    .pushMpls()
                    .setMpls(MplsLabel.mplsLabel(106));
            toAddBuckets.add(DefaultGroupBucket.createSelectGroupBucket(
                                                        tBuilder.build()));
        }
        GroupBuckets toAddGroupBuckets = new GroupBuckets(toAddBuckets);
        buckets.addAll(toAddBuckets);
        GroupBuckets updatedGroupBuckets = new GroupBuckets(buckets);
        InternalGroupStoreDelegate updateGroupDescDelegate =
                new InternalGroupStoreDelegate(addKey,
                                               updatedGroupBuckets,
                                               GroupEvent.Type.GROUP_UPDATE_REQUESTED);
        simpleGroupStore.setDelegate(updateGroupDescDelegate);
        simpleGroupStore.updateGroupDescription(D1,
                                                currKey,
                                                UpdateType.ADD,
                                                toAddGroupBuckets,
                                                addKey);
        simpleGroupStore.unsetDelegate(updateGroupDescDelegate);

        short weight = 5;
        toAddBuckets = new ArrayList<>();
        for (PortNumber portNumber: newOutPorts) {
            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
            tBuilder.setOutput(portNumber)
                    .setEthDst(MacAddress.valueOf("00:00:00:00:00:03"))
                    .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                    .pushMpls()
                    .setMpls(MplsLabel.mplsLabel(106));
            toAddBuckets.add(DefaultGroupBucket.createSelectGroupBucket(
                    tBuilder.build(), weight));
        }

        toAddGroupBuckets = new GroupBuckets(toAddBuckets);
        buckets = new ArrayList<>();
        buckets.addAll(existingGroup.buckets().buckets());
        buckets.addAll(toAddBuckets);
        updatedGroupBuckets = new GroupBuckets(buckets);
        updateGroupDescDelegate =
                new InternalGroupStoreDelegate(addKey,
                                               updatedGroupBuckets,
                                               GroupEvent.Type.GROUP_UPDATE_REQUESTED);
        simpleGroupStore.setDelegate(updateGroupDescDelegate);
        simpleGroupStore.updateGroupDescription(D1,
                                                addKey,
                                                UpdateType.ADD,
                                                toAddGroupBuckets,
                                                addKey);
        simpleGroupStore.unsetDelegate(updateGroupDescDelegate);
    }

    // Testing updateGroupDescription for REMOVE operation from northbound
    private void testRemoveBuckets(GroupKey currKey, GroupKey removeKey) {
        Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
        List<GroupBucket> buckets = new ArrayList<>();
        buckets.addAll(existingGroup.buckets().buckets());

        List<GroupBucket> toRemoveBuckets = new ArrayList<>();

        // There should be 4 buckets in the current group
        toRemoveBuckets.add(buckets.remove(0));
        toRemoveBuckets.add(buckets.remove(1));
        GroupBuckets toRemoveGroupBuckets = new GroupBuckets(toRemoveBuckets);

        GroupBuckets remainingGroupBuckets = new GroupBuckets(buckets);
        InternalGroupStoreDelegate removeGroupDescDelegate =
                new InternalGroupStoreDelegate(removeKey,
                                               remainingGroupBuckets,
                                               GroupEvent.Type.GROUP_UPDATE_REQUESTED);
        simpleGroupStore.setDelegate(removeGroupDescDelegate);
        simpleGroupStore.updateGroupDescription(D1,
                                                currKey,
                                                UpdateType.REMOVE,
                                                toRemoveGroupBuckets,
                                                removeKey);
        simpleGroupStore.unsetDelegate(removeGroupDescDelegate);
    }

    // Testing deleteGroupDescription operation from northbound
    private void testDeleteGroup(GroupKey currKey) {
        Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
        InternalGroupStoreDelegate deleteGroupDescDelegate =
                new InternalGroupStoreDelegate(currKey,
                                               existingGroup.buckets(),
                                               GroupEvent.Type.GROUP_REMOVE_REQUESTED);
        simpleGroupStore.setDelegate(deleteGroupDescDelegate);
        simpleGroupStore.deleteGroupDescription(D1, currKey);
        simpleGroupStore.unsetDelegate(deleteGroupDescDelegate);
    }

    // Testing deleteGroupDescription operation from northbound
    private void testDeleteGroupOnDevice(GroupKey currKey) {
        assertThat(simpleGroupStore.getGroupCount(D1), is(1));
        simpleGroupStore.purgeGroupEntry(D1);
        assertThat(simpleGroupStore.getGroupCount(D1), is(0));
    }

    // Testing removeGroupEntry operation from southbound
    private void testRemoveGroupFromSB(GroupKey currKey) {
        Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
        InternalGroupStoreDelegate removeGroupEntryDelegate =
                new InternalGroupStoreDelegate(currKey,
                                               existingGroup.buckets(),
                                               GroupEvent.Type.GROUP_REMOVED);
        simpleGroupStore.setDelegate(removeGroupEntryDelegate);
        simpleGroupStore.removeGroupEntry(existingGroup);

        // Testing getGroup operation
        existingGroup = simpleGroupStore.getGroup(D1, currKey);
        assertEquals(null, existingGroup);
        assertEquals(0, Iterables.size(simpleGroupStore.getGroups(D1)));
        assertEquals(0, simpleGroupStore.getGroupCount(D1));

        simpleGroupStore.unsetDelegate(removeGroupEntryDelegate);
    }

    @Test
    public void testGroupOperationFailure() {

        simpleGroupStore.deviceInitialAuditCompleted(D1, true);

        ApplicationId appId =
                new DefaultApplicationId(2, "org.groupstore.test");
        GroupKey key = new DefaultGroupKey("group1".getBytes());
        PortNumber[] ports = {PortNumber.portNumber(31),
                PortNumber.portNumber(32)};
        List<PortNumber> outPorts = new ArrayList<>();
        outPorts.add(ports[0]);
        outPorts.add(ports[1]);

        List<GroupBucket> buckets = new ArrayList<>();
        for (PortNumber portNumber: outPorts) {
            TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
            tBuilder.setOutput(portNumber)
                    .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
                    .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                    .pushMpls()
                    .setMpls(MplsLabel.mplsLabel(106));
            buckets.add(DefaultGroupBucket.createSelectGroupBucket(
                    tBuilder.build()));
        }
        GroupBuckets groupBuckets = new GroupBuckets(buckets);
        GroupDescription groupDesc = new DefaultGroupDescription(
                D1,
                Group.Type.SELECT,
                groupBuckets,
                key,
                null,
                appId);
        InternalGroupStoreDelegate checkStoreGroupDelegate =
                new InternalGroupStoreDelegate(key,
                        groupBuckets,
                        GroupEvent.Type.GROUP_ADD_REQUESTED);
        simpleGroupStore.setDelegate(checkStoreGroupDelegate);
        // Testing storeGroup operation
        simpleGroupStore.storeGroupDescription(groupDesc);
        simpleGroupStore.unsetDelegate(checkStoreGroupDelegate);

        // Testing Group add operation failure
        Group createdGroup = simpleGroupStore.getGroup(D1, key);
        checkStoreGroupDelegate.verifyGroupId(createdGroup.id());

        GroupOperation groupAddOp = GroupOperation.
                createAddGroupOperation(createdGroup.id(),
                        createdGroup.type(),
                        createdGroup.buckets());
        InternalGroupStoreDelegate checkGroupAddFailureDelegate =
                new InternalGroupStoreDelegate(key,
                        groupBuckets,
                        GroupEvent.Type.GROUP_ADD_FAILED);
        simpleGroupStore.setDelegate(checkGroupAddFailureDelegate);
        simpleGroupStore.groupOperationFailed(D1, groupAddOp);


        // Testing Group modify operation failure
        simpleGroupStore.unsetDelegate(checkGroupAddFailureDelegate);
        GroupOperation groupModOp = GroupOperation.
                createModifyGroupOperation(createdGroup.id(),
                        createdGroup.type(),
                        createdGroup.buckets());
        InternalGroupStoreDelegate checkGroupModFailureDelegate =
                new InternalGroupStoreDelegate(key,
                        groupBuckets,
                        GroupEvent.Type.GROUP_UPDATE_FAILED);
        simpleGroupStore.setDelegate(checkGroupModFailureDelegate);
        simpleGroupStore.groupOperationFailed(D1, groupModOp);

        // Testing Group modify operation failure
        simpleGroupStore.unsetDelegate(checkGroupModFailureDelegate);
        GroupOperation groupDelOp = GroupOperation.
                createDeleteGroupOperation(createdGroup.id(),
                        createdGroup.type());
        InternalGroupStoreDelegate checkGroupDelFailureDelegate =
                new InternalGroupStoreDelegate(key,
                        groupBuckets,
                        GroupEvent.Type.GROUP_REMOVE_FAILED);
        simpleGroupStore.setDelegate(checkGroupDelFailureDelegate);
        simpleGroupStore.groupOperationFailed(D1, groupDelOp);
    }
}

