/*
 * Copyright 2018-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.openstackvtap.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.KryoNamespace;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.openstackvtap.api.OpenstackVtap;
import org.onosproject.openstackvtap.api.OpenstackVtap.Type;
import org.onosproject.openstackvtap.api.OpenstackVtapEvent;
import org.onosproject.openstackvtap.api.OpenstackVtapId;
import org.onosproject.openstackvtap.api.OpenstackVtapNetwork;
import org.onosproject.openstackvtap.api.OpenstackVtapStore;
import org.onosproject.openstackvtap.api.OpenstackVtapStoreDelegate;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.DistributedPrimitive.Status;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.MapEventListener;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.Versioned;
import org.slf4j.Logger;

import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.DefaultAnnotations.merge;
import static org.onosproject.store.service.Versioned.valueOrNull;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Manages the inventory of openstack vtap and openstack vtap network using a {@code ConsistentMap}.
 */
@Component(immediate = true)
@Service
public class DistributedOpenstackVtapStore
        extends AbstractStore<OpenstackVtapEvent, OpenstackVtapStoreDelegate>
        implements OpenstackVtapStore {

    private final Logger log = getLogger(getClass());

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

    private ConsistentMap<OpenstackVtapId, DefaultOpenstackVtap> vtapConsistentMap;
    private MapEventListener<OpenstackVtapId, DefaultOpenstackVtap> vtapListener =
            new VtapEventListener();
    private Map<OpenstackVtapId, DefaultOpenstackVtap> vtapMap;

    private ConsistentMap<Integer, DefaultOpenstackVtapNetwork> vtapNetworkConsistentMap;
    private MapEventListener<Integer, DefaultOpenstackVtapNetwork> vtapNetworkListener =
            new VtapNetworkEventListener();
    private Map<Integer, DefaultOpenstackVtapNetwork> vtapNetworkMap;

    private ConsistentMap<Integer, Set<DeviceId>> vtapNetworkDevicesConsistentMap;

    private static final Serializer SERIALIZER = Serializer
            .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
                    .register(OpenstackVtapId.class)
                    .register(UUID.class)
                    .register(DefaultOpenstackVtap.class)
                    .register(Type.class)
                    .register(DefaultOpenstackVtapCriterion.class)
                    .register(DefaultOpenstackVtapNetwork.class)
                    .register(OpenstackVtapNetwork.Mode.class)
                    .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
                    .build());

    private Map<DeviceId, Set<OpenstackVtapId>>
                                    vtapIdsByTxDeviceId = Maps.newConcurrentMap();
    private Map<DeviceId, Set<OpenstackVtapId>>
                                    vtapIdsByRxDeviceId = Maps.newConcurrentMap();

    private ScheduledExecutorService eventExecutor;
    private Consumer<Status> vtapStatusListener;

    private static final String ERR_NOT_FOUND = "ID {} does not exist";
    private static final String ERR_DUPLICATE = "ID {} already exists";

    @Activate
    public void activate() {
        eventExecutor = newSingleThreadScheduledExecutor(
                groupedThreads(this.getClass().getSimpleName(), "event-handler", log));

        // vtap network data
        vtapNetworkConsistentMap = storageService.<Integer, DefaultOpenstackVtapNetwork>
                consistentMapBuilder()
                .withName("vtapNetworkMap")
                .withSerializer(SERIALIZER)
                .build();
        vtapNetworkMap = vtapNetworkConsistentMap.asJavaMap();
        vtapNetworkConsistentMap.addListener(vtapNetworkListener);

        // vtap network devices data
        vtapNetworkDevicesConsistentMap = storageService.<Integer, Set<DeviceId>>
                consistentMapBuilder()
                .withName("vtapNetworkDevicesMap")
                .withSerializer(SERIALIZER)
                .build();

        // vtap data
        vtapConsistentMap = storageService.<OpenstackVtapId, DefaultOpenstackVtap>
                consistentMapBuilder()
                .withName("vtapMap")
                .withSerializer(SERIALIZER)
                .build();
        vtapMap = vtapConsistentMap.asJavaMap();
        vtapConsistentMap.addListener(vtapListener);

        // initialize vtap data
        vtapStatusListener = status -> {
            if (status == Status.ACTIVE) {
                eventExecutor.execute(this::loadVtapIds);
            }
        };
        vtapConsistentMap.addStatusChangeListener(vtapStatusListener);

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        vtapConsistentMap.removeStatusChangeListener(vtapStatusListener);
        vtapConsistentMap.removeListener(vtapListener);
        vtapNetworkConsistentMap.removeListener(vtapNetworkListener);

        eventExecutor.shutdown();

        log.info("Stopped");
    }

    private boolean shouldUpdateVtapNetwork(DefaultOpenstackVtapNetwork existing,
                                            OpenstackVtapNetwork description) {
        if (existing == null) {
            return true;
        }

        if (!Objects.equals(existing.mode(), description.mode()) ||
                !Objects.equals(existing.networkId(), description.networkId()) ||
                !Objects.equals(existing.serverIp(), description.serverIp())) {
            return true;
        }

        // check to see if any of the annotations provided by description
        // differ from those in the existing vtap network
        return description.annotations().keys().stream()
                .anyMatch(k -> !Objects.equals(description.annotations().value(k),
                        existing.annotations().value(k)));
    }

    private OpenstackVtapNetwork createOrUpdateVtapNetwork(boolean update,
                                                           Integer key,
                                                           OpenstackVtapNetwork description) {
        DefaultOpenstackVtapNetwork result =
                vtapNetworkMap.compute(key, (id, existing) -> {
                    // Check create or update validity
                    if (update && existing == null) {
                        return null;
                    } else if (!update && existing != null) {
                        return existing;
                    }

                    if (shouldUpdateVtapNetwork(existing, description)) {
                        // Replace or add annotations
                        final SparseAnnotations annotations;
                        if (existing != null) {
                            annotations = merge((DefaultAnnotations) existing.annotations(),
                                    (SparseAnnotations) description.annotations());
                        } else {
                            annotations = (SparseAnnotations) description.annotations();
                        }

                        return DefaultOpenstackVtapNetwork.builder(description)
                                .annotations(annotations)
                                .build();
                    }
                    return existing;
                });
        return result;
    }

    @Override
    public OpenstackVtapNetwork createVtapNetwork(Integer key, OpenstackVtapNetwork description) {
        if (getVtapNetwork(key) == null) {
            OpenstackVtapNetwork vtapNetwork = createOrUpdateVtapNetwork(false, key, description);
            if (Objects.equals(vtapNetwork, description)) {
                return vtapNetwork;
            }
        }
        log.error(ERR_DUPLICATE, key);
        return null;
    }

    @Override
    public OpenstackVtapNetwork updateVtapNetwork(Integer key, OpenstackVtapNetwork description) {
        OpenstackVtapNetwork vtapNetwork = createOrUpdateVtapNetwork(true, key, description);
        if (vtapNetwork == null) {
            log.error(ERR_NOT_FOUND, key);
        }
        return vtapNetwork;
    }

    @Override
    public OpenstackVtapNetwork removeVtapNetwork(Integer key) {
        return vtapNetworkMap.remove(key);
    }

    @Override
    public void clearVtapNetworks() {
        vtapNetworkMap.clear();
    }

    @Override
    public int getVtapNetworkCount() {
        return vtapNetworkMap.size();
    }

    @Override
    public OpenstackVtapNetwork getVtapNetwork(Integer key) {
        return vtapNetworkMap.get(key);
    }

    @Override
    public boolean addDeviceToVtapNetwork(Integer key, DeviceId deviceId) {
        Versioned<Set<DeviceId>> result =
                vtapNetworkDevicesConsistentMap.compute(key, (id, existing) -> {
                    // Add deviceId to deviceIds
                    if (existing == null) {
                        return Sets.newHashSet(deviceId);
                    } else if (!existing.contains(deviceId)) {
                        Set<DeviceId> deviceIds = Sets.newHashSet(existing);
                        deviceIds.add(deviceId);
                        return deviceIds;
                    } else {
                        return existing;
                    }
                });
        return Objects.nonNull(valueOrNull(result));
    }

    @Override
    public boolean removeDeviceFromVtapNetwork(Integer key, DeviceId deviceId) {
        Versioned<Set<DeviceId>> result =
                vtapNetworkDevicesConsistentMap.compute(key, (id, existing) -> {
                    // Remove deviceId from deviceIds
                    if (existing != null && existing.contains(deviceId)) {
                        Set<DeviceId> deviceIds = Sets.newHashSet(existing);
                        deviceIds.remove(deviceId);
                        return deviceIds;
                    } else {
                        return existing;
                    }
                });
        return Objects.nonNull(valueOrNull(result));
    }

    @Override
    public Set<DeviceId> getVtapNetworkDevices(Integer key) {
        return valueOrNull(vtapNetworkDevicesConsistentMap.get(key));
    }

    private boolean shouldUpdateVtap(DefaultOpenstackVtap existing,
                                     OpenstackVtap description,
                                     boolean replaceDevices) {
        if (existing == null) {
            return true;
        }

        if (!Objects.equals(existing.type(), description.type()) ||
                !Objects.equals(existing.vtapCriterion(), description.vtapCriterion())) {
            return true;
        }

        if (replaceDevices) {
            if (!Objects.equals(description.txDeviceIds(), existing.txDeviceIds()) ||
                    !Objects.equals(description.rxDeviceIds(), existing.rxDeviceIds())) {
                return true;
            }
        } else {
            if (!existing.txDeviceIds().containsAll(description.txDeviceIds()) ||
                    !existing.rxDeviceIds().containsAll(description.rxDeviceIds())) {
                return true;
            }
        }

        // check to see if any of the annotations provided by description
        // differ from those in the existing vtap
        return description.annotations().keys().stream()
                .anyMatch(k -> !Objects.equals(description.annotations().value(k),
                        existing.annotations().value(k)));
    }

    private OpenstackVtap createOrUpdateVtap(boolean update,
                                             OpenstackVtap description,
                                             boolean replaceDevices) {
        DefaultOpenstackVtap result =
                vtapMap.compute(description.id(), (id, existing) -> {
                    // Check create or update validity
                    if (update && existing == null) {
                        return null;
                    } else if (!update && existing != null) {
                        return existing;
                    }

                    if (shouldUpdateVtap(existing, description, replaceDevices)) {
                        // Replace or add devices
                        final Set<DeviceId> txDeviceIds;
                        if (existing == null || replaceDevices) {
                            txDeviceIds = description.txDeviceIds();
                        } else {
                            txDeviceIds = Sets.newHashSet(existing.txDeviceIds());
                            txDeviceIds.addAll(description.txDeviceIds());
                        }

                        final Set<DeviceId> rxDeviceIds;
                        if (existing == null || replaceDevices) {
                            rxDeviceIds = description.rxDeviceIds();
                        } else {
                            rxDeviceIds = Sets.newHashSet(existing.rxDeviceIds());
                            rxDeviceIds.addAll(description.rxDeviceIds());
                        }

                        // Replace or add annotations
                        final SparseAnnotations annotations;
                        if (existing != null) {
                            annotations = merge((DefaultAnnotations) existing.annotations(),
                                    (SparseAnnotations) description.annotations());
                        } else {
                            annotations = (SparseAnnotations) description.annotations();
                        }

                        return DefaultOpenstackVtap.builder(description)
                                .txDeviceIds(txDeviceIds)
                                .rxDeviceIds(rxDeviceIds)
                                .annotations(annotations)
                                .build();
                    }
                    return existing;
                });
        return result;
    }

    @Override
    public OpenstackVtap createVtap(OpenstackVtap description) {
        if (getVtap(description.id()) == null) {
            OpenstackVtap vtap = createOrUpdateVtap(false, description, true);
            if (Objects.equals(vtap, description)) {
                return vtap;
            }
        }
        log.error(ERR_DUPLICATE, description.id());
        return null;
    }

    @Override
    public OpenstackVtap updateVtap(OpenstackVtap description, boolean replaceDevices) {
        OpenstackVtap vtap = createOrUpdateVtap(true, description, replaceDevices);
        if (vtap == null) {
            log.error(ERR_NOT_FOUND, description.id());
        }
        return vtap;
    }

    @Override
    public OpenstackVtap removeVtap(OpenstackVtapId vtapId) {
        return vtapMap.remove(vtapId);
    }

    @Override
    public void clearVtaps() {
        vtapMap.clear();
    }

    @Override
    public int getVtapCount(Type type) {
        return (int) vtapMap.values().parallelStream()
                .filter(vtap -> vtap.type().isValid(type))
                .count();
    }

    @Override
    public Set<OpenstackVtap> getVtaps(Type type) {
        return ImmutableSet.copyOf(
                vtapMap.values().parallelStream()
                        .filter(vtap -> vtap.type().isValid(type))
                        .collect(Collectors.toSet()));
    }

    @Override
    public OpenstackVtap getVtap(OpenstackVtapId vtapId) {
        return vtapMap.get(vtapId);
    }

    @Override
    public boolean addDeviceToVtap(OpenstackVtapId vtapId, Type type, DeviceId deviceId) {
        OpenstackVtap result =
                vtapMap.compute(vtapId, (id, existing) -> {
                    if (existing == null) {
                        return null;
                    }

                    // Check type validate
                    if (!existing.type().isValid(type)) {
                        log.error("Not valid OpenstackVtap type {} for requested type {}", existing.type(), type);
                        return existing;
                    }

                    // Add deviceId to txDeviceIds
                    final Set<DeviceId> txDeviceIds;
                    if (existing.type().isValid(Type.VTAP_TX) &&
                            (type.isValid(Type.VTAP_TX) || type == Type.VTAP_ANY) &&
                            !existing.txDeviceIds().contains(deviceId)) {
                        txDeviceIds = Sets.newHashSet(existing.txDeviceIds());
                        txDeviceIds.add(deviceId);
                    } else {
                        txDeviceIds = null;
                    }

                    // Add deviceId to rxDeviceIds
                    final Set<DeviceId> rxDeviceIds;
                    if (existing.type().isValid(Type.VTAP_RX) &&
                            (type.isValid(Type.VTAP_RX) || type == Type.VTAP_ANY) &&
                            !existing.rxDeviceIds().contains(deviceId)) {
                        rxDeviceIds = Sets.newHashSet(existing.rxDeviceIds());
                        rxDeviceIds.add(deviceId);
                    } else {
                        rxDeviceIds = null;
                    }

                    if (txDeviceIds != null || rxDeviceIds != null) {
                        return DefaultOpenstackVtap.builder()
                                .id(id)
                                .type(existing.type())
                                .vtapCriterion(existing.vtapCriterion())
                                .txDeviceIds(txDeviceIds != null ? txDeviceIds : existing.txDeviceIds())
                                .rxDeviceIds(rxDeviceIds != null ? rxDeviceIds : existing.rxDeviceIds())
                                .annotations(existing.annotations())
                                .build();
                    } else {
                        return existing;
                    }
                });
        return Objects.nonNull(result);
    }

    @Override
    public boolean removeDeviceFromVtap(OpenstackVtapId vtapId, OpenstackVtap.Type type, DeviceId deviceId) {
        OpenstackVtap result =
                vtapMap.compute(vtapId, (id, existing) -> {
                    if (existing == null) {
                        return null;
                    }

                    // Check type validate
                    if (!existing.type().isValid(type)) {
                        log.error("Not valid OpenstackVtap type {} for requested type {}",
                                existing.type(), type);
                        return existing;
                    }

                    // Remove deviceId from txDeviceIds
                    final Set<DeviceId> txDeviceIds;
                    if (existing.type().isValid(Type.VTAP_TX) &&
                            (type.isValid(Type.VTAP_TX) || type == Type.VTAP_ANY) &&
                            existing.txDeviceIds().contains(deviceId)) {
                        txDeviceIds = Sets.newHashSet(existing.txDeviceIds());
                        txDeviceIds.remove(deviceId);
                    } else {
                        txDeviceIds = null;
                    }

                    // Remove deviceId from rxDeviceIds
                    final Set<DeviceId> rxDeviceIds;
                    if (existing.type().isValid(Type.VTAP_RX) &&
                            (type.isValid(Type.VTAP_RX) || type == Type.VTAP_ANY) &&
                            existing.rxDeviceIds().contains(deviceId)) {
                        rxDeviceIds = Sets.newHashSet(existing.rxDeviceIds());
                        rxDeviceIds.remove(deviceId);
                    } else {
                        rxDeviceIds = null;
                    }

                    if (txDeviceIds != null || rxDeviceIds != null) {
                        return DefaultOpenstackVtap.builder()
                                .id(id)
                                .type(existing.type())
                                .vtapCriterion(existing.vtapCriterion())
                                .txDeviceIds(txDeviceIds != null ? txDeviceIds : existing.txDeviceIds())
                                .rxDeviceIds(rxDeviceIds != null ? rxDeviceIds : existing.rxDeviceIds())
                                .annotations(existing.annotations())
                                .build();
                    } else {
                        return existing;
                    }
                });
        return Objects.nonNull(result);
    }

    @Override
    public Set<OpenstackVtap> getVtapsByDeviceId(DeviceId deviceId) {
        Set<OpenstackVtapId> vtapIds = Sets.newHashSet();
        Set<OpenstackVtapId> txIds = vtapIdsByTxDeviceId.get(deviceId);
        if (txIds != null) {
            vtapIds.addAll(txIds);
        }
        Set<OpenstackVtapId> rxIds = vtapIdsByRxDeviceId.get(deviceId);
        if (rxIds != null) {
            vtapIds.addAll(rxIds);
        }
        return ImmutableSet.copyOf(
                vtapIds.parallelStream()
                        .map(vtapId -> vtapMap.get(vtapId))
                        .filter(Objects::nonNull)
                        .collect(Collectors.toSet()));
    }

    private class VtapComparator implements Comparator<OpenstackVtap> {
        @Override
        public int compare(OpenstackVtap v1, OpenstackVtap v2) {
            int diff = (v2.type().compareTo(v1.type()));
            if (diff == 0) {
                return (v2.vtapCriterion().ipProtocol() - v1.vtapCriterion().ipProtocol());
            }
            return diff;
        }
    }

    private void loadVtapIds() {
        vtapIdsByTxDeviceId.clear();
        vtapIdsByRxDeviceId.clear();
        vtapMap.values().forEach(vtap -> refreshDeviceIdsByVtap(null, vtap));
    }

    private static Set<OpenstackVtapId> addVTapIds(OpenstackVtapId vtapId) {
        Set<OpenstackVtapId> vtapIds = Sets.newConcurrentHashSet();
        vtapIds.add(vtapId);
        return vtapIds;
    }

    private static Set<OpenstackVtapId> updateVTapIds(Set<OpenstackVtapId> existingVtapIds,
                                                      OpenstackVtapId vtapId) {
        existingVtapIds.add(vtapId);
        return existingVtapIds;
    }

    private static Set<OpenstackVtapId> removeVTapIds(Set<OpenstackVtapId> existingVtapIds,
                                                      OpenstackVtapId vtapId) {
        existingVtapIds.remove(vtapId);
        if (existingVtapIds.isEmpty()) {
            return null;
        }
        return existingVtapIds;
    }

    private void updateVTapIdFromTxDeviceId(OpenstackVtapId vtapId, DeviceId deviceId) {
        vtapIdsByTxDeviceId.compute(deviceId, (k, v) -> v == null ?
                addVTapIds(vtapId) : updateVTapIds(v, vtapId));
    }

    private void removeVTapIdFromTxDeviceId(OpenstackVtapId vtapId, DeviceId deviceId) {
        vtapIdsByTxDeviceId.computeIfPresent(deviceId, (k, v) -> removeVTapIds(v, vtapId));
    }

    private void updateVTapIdFromRxDeviceId(OpenstackVtapId vtapId, DeviceId deviceId) {
        vtapIdsByRxDeviceId.compute(deviceId, (k, v) -> v == null ?
                addVTapIds(vtapId) : updateVTapIds(v, vtapId));
    }

    private void removeVTapIdFromRxDeviceId(OpenstackVtapId vtapId, DeviceId deviceId) {
        vtapIdsByRxDeviceId.computeIfPresent(deviceId, (k, v) -> removeVTapIds(v, vtapId));
    }

    private void refreshDeviceIdsByVtap(OpenstackVtap newOpenstackVtap,
                                        OpenstackVtap oldOpenstackVtap) {
        if (Objects.equals(newOpenstackVtap, oldOpenstackVtap)) {
            return;
        }

        if (oldOpenstackVtap != null) {
            Set<DeviceId> removeDeviceIds;

            // Remove TX vtap
            removeDeviceIds = (newOpenstackVtap != null) ?
                    Sets.difference(oldOpenstackVtap.txDeviceIds(),
                            newOpenstackVtap.txDeviceIds()) : oldOpenstackVtap.txDeviceIds();
            removeDeviceIds.forEach(id -> removeVTapIdFromTxDeviceId(oldOpenstackVtap.id(), id));

            // Remove RX vtap
            removeDeviceIds = (newOpenstackVtap != null) ?
                    Sets.difference(oldOpenstackVtap.rxDeviceIds(),
                            newOpenstackVtap.rxDeviceIds()) : oldOpenstackVtap.rxDeviceIds();
            removeDeviceIds.forEach(id -> removeVTapIdFromRxDeviceId(oldOpenstackVtap.id(), id));
        }

        if (newOpenstackVtap != null) {
            Set<DeviceId> addDeviceIds;

            // Add TX vtap
            addDeviceIds = (oldOpenstackVtap != null) ?
                    Sets.difference(newOpenstackVtap.txDeviceIds(),
                            oldOpenstackVtap.txDeviceIds()) : newOpenstackVtap.txDeviceIds();
            addDeviceIds.forEach(id -> updateVTapIdFromTxDeviceId(newOpenstackVtap.id(), id));

            // Add RX vtap
            addDeviceIds = (oldOpenstackVtap != null) ?
                    Sets.difference(newOpenstackVtap.rxDeviceIds(),
                            oldOpenstackVtap.rxDeviceIds()) : newOpenstackVtap.rxDeviceIds();
            addDeviceIds.forEach(id -> updateVTapIdFromRxDeviceId(newOpenstackVtap.id(), id));
        }
    }

    private class VtapEventListener
            implements MapEventListener<OpenstackVtapId, DefaultOpenstackVtap> {
        @Override
        public void event(MapEvent<OpenstackVtapId, DefaultOpenstackVtap> event) {
            DefaultOpenstackVtap newValue =
                    event.newValue() != null ? event.newValue().value() : null;
            DefaultOpenstackVtap oldValue =
                    event.oldValue() != null ? event.oldValue().value() : null;

            log.trace("VtapEventListener {}: {} -> {}", event.type(), oldValue, newValue);
            switch (event.type()) {
                case INSERT:
                    refreshDeviceIdsByVtap(newValue, oldValue);
                    notifyDelegate(new OpenstackVtapEvent(
                            OpenstackVtapEvent.Type.VTAP_ADDED, newValue, null));
                    break;

                case UPDATE:
                    refreshDeviceIdsByVtap(newValue, oldValue);
                    notifyDelegate(new OpenstackVtapEvent(
                            OpenstackVtapEvent.Type.VTAP_UPDATED, newValue, oldValue));
                    break;

                case REMOVE:
                    refreshDeviceIdsByVtap(newValue, oldValue);
                    notifyDelegate(new OpenstackVtapEvent(
                            OpenstackVtapEvent.Type.VTAP_REMOVED, null, oldValue));
                    break;

                default:
                    log.warn("Unknown map event type: {}", event.type());
            }
        }
    }

    private class VtapNetworkEventListener
            implements MapEventListener<Integer, DefaultOpenstackVtapNetwork> {
        @Override
        public void event(MapEvent<Integer, DefaultOpenstackVtapNetwork> event) {
            DefaultOpenstackVtapNetwork newValue =
                    event.newValue() != null ? event.newValue().value() : null;
            DefaultOpenstackVtapNetwork oldValue =
                    event.oldValue() != null ? event.oldValue().value() : null;

            log.trace("VtapNetworkEventListener {}: {} -> {}", event.type(), oldValue, newValue);
            switch (event.type()) {
                case INSERT:
                    notifyDelegate(new OpenstackVtapEvent(
                            OpenstackVtapEvent.Type.VTAP_NETWORK_ADDED, newValue, null));
                    break;

                case UPDATE:
                    notifyDelegate(new OpenstackVtapEvent(
                            OpenstackVtapEvent.Type.VTAP_NETWORK_UPDATED, newValue, oldValue));
                    break;

                case REMOVE:
                    notifyDelegate(new OpenstackVtapEvent(
                            OpenstackVtapEvent.Type.VTAP_NETWORK_REMOVED, null, oldValue));
                    break;

                default:
                    log.warn("Unknown map event type: {}", event.type());
            }
        }
    }

}
