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

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv6;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.app.ApplicationService;
import org.onosproject.component.ComponentService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.intf.InterfaceEvent;
import org.onosproject.net.intf.InterfaceListener;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketService;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onosproject.simplefabric.api.FabricNetwork;
import org.onosproject.simplefabric.api.FabricRoute;
import org.onosproject.simplefabric.api.FabricSubnet;
import org.onosproject.simplefabric.api.SimpleFabricEvent;
import org.onosproject.simplefabric.api.SimpleFabricListener;
import org.onosproject.simplefabric.api.SimpleFabricService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static org.onosproject.routeservice.RouteTools.createBinaryString;
import static org.onosproject.simplefabric.api.Constants.ALLOW_ETH_ADDRESS_SELECTOR;
import static org.onosproject.simplefabric.api.Constants.ALLOW_IPV6;
import static org.onosproject.simplefabric.api.Constants.APP_ID;
import static org.onosproject.simplefabric.api.Constants.IDLE_INTERVAL_MSEC;
import static org.onosproject.simplefabric.api.Constants.REACTIVE_ALLOW_LINK_CP;
import static org.onosproject.simplefabric.api.Constants.REACTIVE_HASHED_PATH_SELECTION;
import static org.onosproject.simplefabric.api.Constants.REACTIVE_MATCH_IP_PROTO;
import static org.onosproject.simplefabric.api.Constants.REACTIVE_SINGLE_TO_SINGLE;


/**
 * Reactive routing configuration manager.
 */
@Component(immediate = true, service = SimpleFabricService.class)
public class SimpleFabricManager extends ListenerRegistry<SimpleFabricEvent, SimpleFabricListener>
        implements SimpleFabricService {

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected ApplicationService applicationService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected NetworkConfigService configService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected NetworkConfigRegistry registry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected InterfaceService interfaceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected HostService hostService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected PacketService packetService;

    // compoents to be activated within SimpleFabric
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected ComponentService componentService;

    // SimpleFabric variables
    private ApplicationId appId = null;

    // fabric networks
    private Set<FabricNetwork> fabricNetworks = new HashSet<>();
    private Set<Interface> networkInterfaces = new HashSet<>();

    // Subnet table
    private Set<FabricSubnet> fabricSubnets = new HashSet<>();
    private InvertedRadixTree<FabricSubnet> ip4SubnetTable =
                 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
    private InvertedRadixTree<FabricSubnet> ip6SubnetTable =
                 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());

    // Fabric Route table
    private Set<FabricRoute> fabricRoutes = new HashSet<>();
    private InvertedRadixTree<FabricRoute> ip4BorderRouteTable =
                 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
    private InvertedRadixTree<FabricRoute> ip6BorderRouteTable =
                 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());

    // Virtual gateway
    private Map<IpAddress, MacAddress> virtualGatewayIpMacMap = Maps.newConcurrentMap();

    // Refresh monitor thread
    private Object refreshMonitor = new Object();
    private boolean doRefresh = false;
    private boolean doFlush = false;
    private InternalRefreshThread refreshThread;

    // Listener for Service Events
    private final InternalNetworkConfigListener configListener = new InternalNetworkConfigListener();
    private final InternalDeviceListener deviceListener = new InternalDeviceListener();
    private final InternalHostListener hostListener = new InternalHostListener();

    private ConfigFactory<ApplicationId, SimpleFabricConfig> simpleFabricConfigFactory =
        new ConfigFactory<ApplicationId, SimpleFabricConfig>(
                SubjectFactories.APP_SUBJECT_FACTORY,
                SimpleFabricConfig.class, SimpleFabricConfig.KEY) {
        @Override
        public SimpleFabricConfig createConfig() {
            return new SimpleFabricConfig();
       }
    };

    @Activate
    public void activate() {
        log.info("simple fabric starting");

        if (appId == null) {
            appId = coreService.registerApplication(APP_ID);
        }

        // initial refresh
        refresh();

        configService.addListener(configListener);
        registry.registerConfigFactory(simpleFabricConfigFactory);
        deviceService.addListener(deviceListener);
        hostService.addListener(hostListener);

        componentService.activate(appId, SimpleFabricNeighbour.class.getName());
        componentService.activate(appId, SimpleFabricRouting.class.getName());
        if (ALLOW_ETH_ADDRESS_SELECTOR) {
            componentService.activate(appId, SimpleFabricForwarding.class.getName());
        }

        refreshThread = new InternalRefreshThread();
        refreshThread.start();

        log.info("simple fabric started");
    }

    @Deactivate
    public void deactivate() {
        log.info("simple fabric stopping");

        componentService.deactivate(appId, SimpleFabricNeighbour.class.getName());
        componentService.deactivate(appId, SimpleFabricRouting.class.getName());
        if (ALLOW_ETH_ADDRESS_SELECTOR) {
            componentService.deactivate(appId, SimpleFabricForwarding.class.getName());
        }

        deviceService.removeListener(deviceListener);
        hostService.removeListener(hostListener);
        registry.unregisterConfigFactory(simpleFabricConfigFactory);
        configService.removeListener(configListener);

        refreshThread.stop();
        refreshThread = null;

        log.info("simple fabric stopped");
    }

    // Set up from configuration
    // returns found isDirty and refresh listeners are called (true) or not (false)
    private boolean refresh() {
        log.debug("simple fabric refresh");
        boolean dirty = false;

        SimpleFabricConfig config = configService.getConfig(coreService.registerApplication(APP_ID),
                                                            SimpleFabricConfig.class);
        if (config == null) {
            log.debug("No simple fabric config available!");
            return false;
        }

        // fabricNetworks
        Set<FabricNetwork> newFabricNetworks = new HashSet<>();
        Set<Interface> newInterfaces = new HashSet<>();
        for (FabricNetwork newFabricNetworkConfig : config.fabricNetworks()) {
            FabricNetwork newFabricNetwork = DefaultFabricNetwork.of(newFabricNetworkConfig);

            // fill up interfaces and Hosts with active port only
            for (String ifaceName : newFabricNetworkConfig.interfaceNames()) {
                Interface iface = getInterfaceByName(ifaceName);
                if (iface != null && deviceService.isAvailable(iface.connectPoint().deviceId())) {
                     newFabricNetwork.addInterface(iface);
                     newInterfaces.add(iface);
                }
            }
            for (Host host : hostService.getHosts()) {
                // consider host with ip only
                if (!host.ipAddresses().isEmpty()) {
                    Interface iface = findAvailableDeviceHostInterface(host);
                    if (iface != null && newFabricNetwork.contains(iface)) {
                        newFabricNetwork.addHost(host);
                    }
                }
            }
            newFabricNetwork.setDirty(true);

            // update newFabricNetwork's isDirty flags if same entry already exists
            for (FabricNetwork prevFabricNetwork : fabricNetworks) {
                if (prevFabricNetwork.equals(newFabricNetwork)) {
                    newFabricNetwork.setDirty(prevFabricNetwork.isDirty());
                    break;
                }
            }
            newFabricNetworks.add(newFabricNetwork);
        }
        if (!fabricNetworks.equals(newFabricNetworks)) {
            fabricNetworks = newFabricNetworks;
            dirty = true;
        }
        if (!networkInterfaces.equals(newInterfaces)) {
            networkInterfaces = newInterfaces;
            dirty = true;
        }

        // default Fabric Subnets
        Set<FabricSubnet> newFabricSubnets = config.fabricSubnets();
        InvertedRadixTree<FabricSubnet> newIp4SubnetTable =
                 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
        InvertedRadixTree<FabricSubnet> newIp6SubnetTable =
                 new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
        Map<IpAddress, MacAddress> newVirtualGatewayIpMacMap = Maps.newConcurrentMap();
        for (FabricSubnet subnet : newFabricSubnets) {
            if (subnet.prefix().isIp4()) {
                newIp4SubnetTable.put(createBinaryString(subnet.prefix()), subnet);
            } else {
                newIp6SubnetTable.put(createBinaryString(subnet.prefix()), subnet);
            }
            newVirtualGatewayIpMacMap.put(subnet.gatewayIp(), subnet.gatewayMac());
        }
        if (!fabricSubnets.equals(newFabricSubnets)) {
            fabricSubnets = newFabricSubnets;
            ip4SubnetTable = newIp4SubnetTable;
            ip6SubnetTable = newIp6SubnetTable;
            dirty = true;
        }
        if (!virtualGatewayIpMacMap.equals(newVirtualGatewayIpMacMap)) {
            virtualGatewayIpMacMap = newVirtualGatewayIpMacMap;
            dirty = true;
        }

        // fabricRoutes config handling
        Set<FabricRoute> newFabricRoutes = config.fabricRoutes();
        if (!fabricRoutes.equals(newFabricRoutes)) {
            InvertedRadixTree<FabricRoute> newIp4BorderRouteTable =
                    new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
            InvertedRadixTree<FabricRoute> newIp6BorderRouteTable =
                    new ConcurrentInvertedRadixTree<>(new DefaultByteArrayNodeFactory());
            for (FabricRoute route : newFabricRoutes) {
                if (route.prefix().isIp4()) {
                    newIp4BorderRouteTable.put(createBinaryString(route.prefix()), route);
                } else {
                    newIp6BorderRouteTable.put(createBinaryString(route.prefix()), route);
                }
            }
            fabricRoutes = newFabricRoutes;
            ip4BorderRouteTable = newIp4BorderRouteTable;
            ip6BorderRouteTable = newIp6BorderRouteTable;
            dirty = true;
        }

        // notify to SimpleFabric listeners
        if (dirty) {
            log.info("simple fabric refresh; notify events");
            process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_UPDATED, "updated"));
        }
        return dirty;
    }

    private Interface getInterfaceByName(String interfaceName) {
        Interface intf = interfaceService.getInterfaces().stream()
                          .filter(iface -> iface.name().equals(interfaceName))
                          .findFirst()
                          .orElse(null);
        if (intf == null) {
            log.warn("simple fabric unknown interface name: {}", interfaceName);
        }
        return intf;
    }

    @Override
    public ApplicationId appId() {
        if (appId == null) {
            appId = coreService.registerApplication(APP_ID);
        }
        return appId;
    }

    @Override
    public Collection<FabricNetwork> fabricNetworks() {
        return ImmutableSet.copyOf(fabricNetworks);
    }

    @Override
    public Set<FabricSubnet> defaultFabricSubnets() {
        return ImmutableSet.copyOf(fabricSubnets);
    }

    @Override
    public Set<FabricRoute> fabricRoutes() {
        return ImmutableSet.copyOf(fabricRoutes);
    }

    @Override
    public boolean isVirtualGatewayMac(MacAddress mac) {
        return virtualGatewayIpMacMap.containsValue(mac);
    }

    @Override
    public boolean isFabricNetworkInterface(Interface intf) {
        return networkInterfaces.contains(intf);
    }

    @Override
    public MacAddress vMacForIp(IpAddress ip) {
        return virtualGatewayIpMacMap.get(ip);
    }

    @Override
    public FabricNetwork fabricNetwork(ConnectPoint port, VlanId vlanId) {
        for (FabricNetwork fabricNetwork : fabricNetworks) {
            if (fabricNetwork.contains(port, vlanId)) {
                return fabricNetwork;
            }
        }
        return null;
    }

    @Override
    public FabricNetwork fabricNetwork(String name) {
        for (FabricNetwork fabricNetwork : fabricNetworks) {
            if (fabricNetwork.name().equals(name)) {
                return fabricNetwork;
            }
        }
        return null;
    }

    @Override
    public FabricSubnet fabricSubnet(IpAddress ip) {
        if (ip.isIp4()) {
            return ip4SubnetTable.getValueForLongestKeyPrefixing(
                     createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)));
        } else {
            return ip6SubnetTable.getValueForLongestKeyPrefixing(
                     createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)));
        }
    }

    @Override
    public FabricRoute fabricRoute(IpAddress ip) {
        // ASSUME: ipAddress is out of fabricSubnet
        if (ip.isIp4()) {
            return ip4BorderRouteTable.getValueForLongestKeyPrefixing(
                     createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)));
        } else {
            return ip6BorderRouteTable.getValueForLongestKeyPrefixing(
                     createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)));
        }
    }


    @Override
    public Interface hostInterface(Host host) {
        return interfaceService.getInterfaces().stream()
                .filter(iface -> iface.connectPoint().equals(host.location()) &&
                                 iface.vlan().equals(host.vlan()))
                .findFirst()
                .orElse(null);
    }

    private Interface findAvailableDeviceHostInterface(Host host) {
        return interfaceService.getInterfaces().stream()
                .filter(iface -> iface.connectPoint().equals(host.location()) &&
                                 iface.vlan().equals(host.vlan()))
                .filter(iface -> deviceService.isAvailable(iface.connectPoint().deviceId()))
                .findFirst()
                .orElse(null);
    }

    @Override
    public boolean requestMac(IpAddress ip) {
        FabricSubnet fabricSubnet = fabricSubnet(ip);
        if (fabricSubnet == null) {
            log.warn("simple fabric request mac failed for unknown fabricSubnet: {}", ip);
            return false;
        }
        FabricNetwork fabricNetwork = fabricNetwork(fabricSubnet.networkName());
        if (fabricNetwork == null) {
            log.warn("simple fabric request mac failed for unknown fabricNetwork name {}: {}",
                     fabricSubnet.networkName(), ip);
            return false;
        }
        log.debug("simple fabric send request mac fabricNetwork {}: {}", fabricNetwork.name(), ip);
        for (Interface iface : fabricNetwork.interfaces()) {
            Ethernet neighbourReq;
            if (ip.isIp4()) {
                neighbourReq = ARP.buildArpRequest(fabricSubnet.gatewayMac().toBytes(),
                                                   fabricSubnet.gatewayIp().toOctets(),
                                                   ip.toOctets(),
                                                   iface.vlan().toShort());
            } else {
                byte[] soliciteIp = IPv6.getSolicitNodeAddress(ip.toOctets());
                neighbourReq = NeighborSolicitation.buildNdpSolicit(
                                                   ip.toOctets(),
                                                   fabricSubnet.gatewayIp().toOctets(),
                                                   soliciteIp,
                                                   fabricSubnet.gatewayMac().toBytes(),
                                                   IPv6.getMCastMacAddress(soliciteIp),
                                                   iface.vlan());
            }
            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                                               .setOutput(iface.connectPoint().port()).build();
            OutboundPacket packet = new DefaultOutboundPacket(iface.connectPoint().deviceId(),
                                               treatment, ByteBuffer.wrap(neighbourReq.serialize()));
            packetService.emit(packet);
        }
        return true;
    }

    @Override
    public void dumpToStream(String subject, OutputStream out) {
        SimpleFabricEvent event = new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_DUMP, subject, out);
        dump(event.subject(), event.out());  // dump in itself
        process(event);  // dump in sub modules
    }

    // Dump handler
    protected void dump(String subject, PrintStream out) {
        if ("show".equals(subject)) {
            out.println("Static Configuration Flag:");
            out.println("    ALLOW_IPV6=" + ALLOW_IPV6);
            out.println("    ALLOW_ETH_ADDRESS_SELECTOR=" + ALLOW_ETH_ADDRESS_SELECTOR);
            out.println("    REACTIVE_SINGLE_TO_SINGLE=" + REACTIVE_SINGLE_TO_SINGLE);
            out.println("    REACTIVE_ALLOW_LINK_CP=" + REACTIVE_ALLOW_LINK_CP);
            out.println("    REACTIVE_HASHED_PATH_SELECTION=" + REACTIVE_HASHED_PATH_SELECTION);
            out.println("    REACTIVE_MATCH_IP_PROTO=" + REACTIVE_MATCH_IP_PROTO);
            out.println("");
            out.println("SimpleFabricAppId:");
            out.println("    " + appId());
            out.println("");
            out.println("fabricNetworks:");
            for (FabricNetwork fabricNetwork : fabricNetworks()) {
                out.println("    " + fabricNetwork);
            }
            out.println("");
            out.println("fabricSubnets:");
            for (FabricSubnet fabricIpSubnet : defaultFabricSubnets()) {
                out.println("    " + fabricIpSubnet);
            }
            out.println("");
            out.println("fabricRoutes:");
            for (FabricRoute route : fabricRoutes()) {
                out.println("    " + route);
            }
        }
    }

    // Refresh action thread and notifier

    private class InternalRefreshThread extends Thread {
        @Override
        public void run() {
            while (true) {
                boolean doRefreshMarked = false;
                boolean doFlushMarked = false;
                synchronized (refreshMonitor) {
                    if (!doRefresh && !doFlush) {
                        try {
                            refreshMonitor.wait(IDLE_INTERVAL_MSEC);
                        } catch (InterruptedException e) {
                            log.warn("run thread interrupted", e);
                            Thread.currentThread().interrupt();
                        }
                    }
                    doRefreshMarked = doRefresh;
                    doRefresh = false;
                    doFlushMarked = doFlush;
                    doFlush = false;
                }
                if (doRefreshMarked) {
                    try {
                        refresh();
                    } catch (Exception e) {
                        log.warn("simple fabric refresh failed: exception={}", e);
                    }
                }
                if (doFlushMarked) {
                    try {
                        log.info("simple fabric flush execute");
                        process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_FLUSH, "flush"));
                    } catch (Exception e) {
                        log.warn("simple fabric flush failed: exception={}", e);
                    }
                }
                if (!doRefreshMarked && !doFlushMarked) {
                    try {
                        if (!refresh()) {
                            process(new SimpleFabricEvent(SimpleFabricEvent.Type.SIMPLE_FABRIC_IDLE, "idle"));
                        }
                    } catch (Exception e) {
                        log.warn("simple fabric idle failed: exception={}", e);
                    }
                }
            }
        }
    }

    @Override
    public void triggerRefresh() {
        synchronized (refreshMonitor) {
            doRefresh = true;
            refreshMonitor.notifyAll();
        }
    }

    @Override
    public void triggerFlush() {
        synchronized (refreshMonitor) {
            doFlush = true;
            refreshMonitor.notifyAll();
        }
    }

    // Service Listeners

    private class InternalNetworkConfigListener implements NetworkConfigListener {
        @Override
        public void event(NetworkConfigEvent event) {
            switch (event.type()) {
            case CONFIG_REGISTERED:
            case CONFIG_UNREGISTERED:
            case CONFIG_ADDED:
            case CONFIG_UPDATED:
            case CONFIG_REMOVED:
                if (event.configClass().equals(SimpleFabricConfig.class)) {
                    triggerRefresh();
                }
                break;
            default:
                break;
            }
        }
    }

    private class InternalDeviceListener implements DeviceListener {
        @Override
        public void event(DeviceEvent event) {
            switch (event.type()) {
            case DEVICE_ADDED:
            case DEVICE_AVAILABILITY_CHANGED:
            case DEVICE_REMOVED:
            case DEVICE_SUSPENDED:
            case DEVICE_UPDATED:
            case PORT_ADDED:
            case PORT_REMOVED:
            case PORT_UPDATED:
            // case PORT_STATS_UPDATED:  IGNORED
                triggerRefresh();
                break;
            default:
                break;
            }
        }
    }

    private class InternalHostListener implements HostListener {
        @Override
        public void event(HostEvent event) {
            Host host = event.subject();
            Host prevHost = event.prevSubject();
            switch (event.type()) {
            case HOST_MOVED:
            case HOST_REMOVED:
            case HOST_ADDED:
            case HOST_UPDATED:
                triggerRefresh();
                break;
            default:
                break;
            }
        }
    }

    private class InternalInterfaceListener implements InterfaceListener {
        @Override
        public void event(InterfaceEvent event) {
            Interface iface = event.subject();
            Interface prevIface = event.prevSubject();
            switch (event.type()) {
            case INTERFACE_ADDED:
            case INTERFACE_REMOVED:
            case INTERFACE_UPDATED:
                triggerRefresh();
                break;
            default:
                break;
            }
        }
    }

}

