/*
 * Copyright 2017-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.evpnopenflow.manager.impl;

import com.fasterxml.jackson.databind.JsonNode;
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.osgi.DefaultServiceDirectory;
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MplsLabel;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.evpnopenflow.manager.EvpnService;
import org.onosproject.evpnopenflow.rsc.VpnAfConfig;
import org.onosproject.evpnopenflow.rsc.VpnInstance;
import org.onosproject.evpnopenflow.rsc.VpnInstanceId;
import org.onosproject.evpnopenflow.rsc.VpnPort;
import org.onosproject.evpnopenflow.rsc.VpnPortId;
import org.onosproject.evpnopenflow.rsc.baseport.BasePortService;
import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigEvent;
import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigListener;
import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigService;
import org.onosproject.evpnopenflow.rsc.vpninstance.VpnInstanceService;
import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortEvent;
import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortListener;
import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortService;
import org.onosproject.gluon.rsc.GluonConfig;
import org.onosproject.incubator.net.resource.label.LabelResource;
import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
import org.onosproject.incubator.net.resource.label.LabelResourceId;
import org.onosproject.incubator.net.resource.label.LabelResourceService;
import org.onosproject.incubator.net.routing.EvpnInstanceName;
import org.onosproject.incubator.net.routing.EvpnInstanceNextHop;
import org.onosproject.incubator.net.routing.EvpnInstancePrefix;
import org.onosproject.incubator.net.routing.EvpnInstanceRoute;
import org.onosproject.incubator.net.routing.EvpnNextHop;
import org.onosproject.incubator.net.routing.EvpnRoute;
import org.onosproject.incubator.net.routing.EvpnRoute.Source;
import org.onosproject.incubator.net.routing.EvpnRouteAdminService;
import org.onosproject.incubator.net.routing.EvpnRouteEvent;
import org.onosproject.incubator.net.routing.EvpnRouteListener;
import org.onosproject.incubator.net.routing.EvpnRouteService;
import org.onosproject.incubator.net.routing.EvpnRouteSet;
import org.onosproject.incubator.net.routing.EvpnRouteStore;
import org.onosproject.incubator.net.routing.Label;
import org.onosproject.incubator.net.routing.RouteDistinguisher;
import org.onosproject.incubator.net.routing.VpnRouteTarget;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.Objective.Operation;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import static com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type.Reference;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ARP_PRIORITY;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ARP_RESPONSE;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BASEPORT;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BGP_EVPN_ROUTE_DELETE_START;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BGP_EVPN_ROUTE_UPDATE_START;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BOTH;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CANNOT_FIND_TUNNEL_PORT_DEVICE;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CANT_FIND_CONTROLLER_DEVICE;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CANT_FIND_VPN_INSTANCE;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CANT_FIND_VPN_PORT;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DELETE;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_OPENFLOW_START;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_OPENFLOW_STOP;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EXPORT_EXTCOMMUNITY;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.FAILED_TO_SET_TUNNEL_DST;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.GET_PRIVATE_LABEL;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.HOST_DETECT;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.HOST_VANISHED;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IFACEID;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IFACEID_OF_HOST_IS_NULL;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IMPORT_EXTCOMMUNITY;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INVALID_EVENT_RECEIVED;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INVALID_ROUTE_TARGET_TYPE;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INVALID_TARGET_RECEIVED;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.MPLS_OUT_FLOWS;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.NETWORK_CONFIG_EVENT_IS_RECEIVED;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.NOT_MASTER_FOR_SPECIFIC_DEVICE;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RELEASE_LABEL_FAILED;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_ADD_ARP_RULES;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_REMOVE_ARP_RULES;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SET;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SLASH;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SWITCH_CHANNEL_ID;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.TUNNEL_DST;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.UPDATE;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_AF_TARGET;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_TARGET;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_BIND;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_TARGET;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_UNBIND;
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VXLAN;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of the EVPN service.
 */
@Component(immediate = true)
@Service
public class EvpnManager implements EvpnService {
    private final Logger log = getLogger(getClass());
    private static final EthType.EtherType ARP_TYPE = EthType.EtherType.ARP;

    protected ApplicationId appId;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected EvpnRouteService evpnRouteService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected EvpnRouteStore evpnRouteStore;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected EvpnRouteAdminService evpnRouteAdminService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService mastershipService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LabelResourceAdminService labelAdminService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LabelResourceService labelService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VpnInstanceService vpnInstanceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowObjectiveService flowObjectiveService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DriverService driverService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VpnPortService vpnPortService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VpnAfConfigService vpnAfConfigService;

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

    public Set<EvpnInstanceRoute> evpnInstanceRoutes = new HashSet<>();
    private final HostListener hostListener = new InnerHostListener();
    private final VpnPortListener vpnPortListner = new InnerVpnPortListener();
    private final VpnAfConfigListener vpnAfConfigListener = new
            InnerVpnAfConfigListener();
    private final InternalRouteEventListener routeListener = new
            InternalRouteEventListener();

    private final NetworkConfigListener configListener = new
            InternalNetworkConfigListener();

    @Activate
    public void activate() {
        appId = coreService.registerApplication(APP_ID);
        hostService.addListener(hostListener);
        vpnPortService.addListener(vpnPortListner);
        vpnAfConfigService.addListener(vpnAfConfigListener);
        configService.addListener(configListener);
        evpnRouteService.addListener(routeListener);

        labelAdminService
                .createGlobalPool(LabelResourceId.labelResourceId(1),
                                  LabelResourceId.labelResourceId(1000));
        log.info(EVPN_OPENFLOW_START);
    }

    @Deactivate
    public void deactivate() {
        hostService.removeListener(hostListener);
        vpnPortService.removeListener(vpnPortListner);
        vpnAfConfigService.removeListener(vpnAfConfigListener);
        configService.removeListener(configListener);
        log.info(EVPN_OPENFLOW_STOP);
    }

    @Override
    public void onBgpEvpnRouteUpdate(EvpnRoute route) {
        if (EvpnRoute.Source.LOCAL.equals(route.source())) {
            return;
        }
        log.info(BGP_EVPN_ROUTE_UPDATE_START, route);
        // deal with public route and transfer to private route
        if (vpnInstanceService.getInstances().isEmpty()) {
            log.info("unable to get instnaces from vpninstance");
            return;
        }

        vpnInstanceService.getInstances().forEach(vpnInstance -> {
            log.info("got instnaces from vpninstance but not entered here");
            List<VpnRouteTarget> vpnImportRouteRt = new
                    LinkedList<>(vpnInstance.getImportRouteTargets());
            List<VpnRouteTarget> expRt = route.exportRouteTarget();
            List<VpnRouteTarget> similar = new LinkedList<>(expRt);
            similar.retainAll(vpnImportRouteRt);

            if (!similar.isEmpty()) {
                EvpnInstancePrefix evpnPrefix = EvpnInstancePrefix
                        .evpnPrefix(route.prefixMac(), route.prefixIp());

                EvpnInstanceNextHop evpnNextHop = EvpnInstanceNextHop
                        .evpnNextHop(route.ipNextHop(), route.label());

                EvpnInstanceRoute evpnPrivateRoute = new
                        EvpnInstanceRoute(vpnInstance.vpnInstanceName(),
                                          route.routeDistinguisher(),
                                          vpnImportRouteRt,
                                          route.exportRouteTarget(),
                                          evpnPrefix,
                                          evpnNextHop,
                                          route.prefixIp(),
                                          route.ipNextHop(),
                                          route.label());

                //update route in route subsystem
                //TODO: added by shahid
                evpnInstanceRoutes.add(evpnPrivateRoute);

            }
        });

        deviceService.getAvailableDevices(Device.Type.SWITCH)
                .forEach(device -> {
                    log.info("switch device is found");
                    Set<Host> hosts = getHostsByVpn(device, route);
                    for (Host h : hosts) {
                        addArpFlows(device.id(),
                                    route,
                                    Objective.Operation.ADD,
                                    h);
                        ForwardingObjective.Builder objective =
                                getMplsOutBuilder(device.id(),
                                                  route,
                                                  h);
                        log.info(MPLS_OUT_FLOWS, h);
                        flowObjectiveService.forward(device.id(),
                                                     objective.add());
                    }
                });
        log.info("no switch device is found");
    }

    @Override
    public void onBgpEvpnRouteDelete(EvpnRoute route) {
        if (EvpnRoute.Source.LOCAL.equals(route.source())) {
            return;
        }
        log.info(BGP_EVPN_ROUTE_DELETE_START, route);
        // deal with public route deleted and transfer to private route
        vpnInstanceService.getInstances().forEach(vpnInstance -> {
            List<VpnRouteTarget> vpnRouteRt = new
                    LinkedList<>(vpnInstance.getImportRouteTargets());
            List<VpnRouteTarget> localRt = route.exportRouteTarget();
            List<VpnRouteTarget> similar = new LinkedList<>(localRt);
            similar.retainAll(vpnRouteRt);

            if (!similar.isEmpty()) {
                EvpnInstancePrefix evpnPrefix = EvpnInstancePrefix
                        .evpnPrefix(route.prefixMac(), route.prefixIp());

                EvpnInstanceNextHop evpnNextHop = EvpnInstanceNextHop
                        .evpnNextHop(route.ipNextHop(), route.label());

                EvpnInstanceRoute evpnPrivateRoute = new
                        EvpnInstanceRoute(vpnInstance.vpnInstanceName(),
                                          route.routeDistinguisher(),
                                          vpnRouteRt,
                                          route.exportRouteTarget(),
                                          evpnPrefix,
                                          evpnNextHop,
                                          route.prefixIp(),
                                          route.ipNextHop(),
                                          route.label());
                //TODO: Added by Shahid
                //evpnRouteAdminService.withdraw(Sets.newHashSet
                //       (evpnPrivateRoute));

            }
        });
        deviceService.getAvailableDevices(Device.Type.SWITCH)
                .forEach(device -> {
                    Set<Host> hosts = getHostsByVpn(device, route);
                    for (Host h : hosts) {
                        addArpFlows(device.id(),
                                    route,
                                    Objective.Operation.REMOVE,
                                    h);
                        ForwardingObjective.Builder objective
                                = getMplsOutBuilder(device.id(),
                                                    route,
                                                    h);
                        flowObjectiveService.forward(device.id(),
                                                     objective.remove());
                    }
                });
    }

    private void addArpFlows(DeviceId deviceId,
                             EvpnRoute route,
                             Operation type,
                             Host host) {
        DriverHandler handler = driverService.createHandler(deviceId);
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthType(ARP_TYPE.ethType().toShort())
                .matchArpTpa(route.prefixIp().address().getIp4Address())
                .matchInPort(host.location().port()).build();

        ExtensionTreatmentResolver resolver = handler
                .behaviour(ExtensionTreatmentResolver.class);
        ExtensionTreatment ethSrcToDst = resolver
                .getExtensionInstruction(ExtensionTreatmentType
                                                 .ExtensionTreatmentTypes
                                                 .NICIRA_MOV_ETH_SRC_TO_DST
                                                 .type());
        ExtensionTreatment arpShaToTha = resolver
                .getExtensionInstruction(ExtensionTreatmentType
                                                 .ExtensionTreatmentTypes
                                                 .NICIRA_MOV_ARP_SHA_TO_THA
                                                 .type());
        ExtensionTreatment arpSpaToTpa = resolver
                .getExtensionInstruction(ExtensionTreatmentType
                                                 .ExtensionTreatmentTypes
                                                 .NICIRA_MOV_ARP_SPA_TO_TPA
                                                 .type());
        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .extension(ethSrcToDst, deviceId).setEthSrc(route.prefixMac())
                .setArpOp(ARP_RESPONSE).extension(arpShaToTha, deviceId)
                .extension(arpSpaToTpa, deviceId).setArpSha(route.prefixMac())
                .setArpSpa(route.prefixIp().address().getIp4Address())
                .setOutput(PortNumber.IN_PORT)
                .build();

        ForwardingObjective.Builder objective = DefaultForwardingObjective
                .builder().withTreatment(treatment).withSelector(selector)
                .fromApp(appId).withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withPriority(ARP_PRIORITY);
        if (type.equals(Objective.Operation.ADD)) {
            log.info(ROUTE_ADD_ARP_RULES);
            flowObjectiveService.forward(deviceId, objective.add());
        } else {
            log.info(ROUTE_REMOVE_ARP_RULES);
            flowObjectiveService.forward(deviceId, objective.remove());
        }
    }

    private Set<Host> getHostsByVpn(Device device, EvpnRoute route) {
        Set<Host> vpnHosts = Sets.newHashSet();
        Set<Host> hosts = hostService.getConnectedHosts(device.id());
        for (Host h : hosts) {
            String ifaceId = h.annotations().value(IFACEID);
            if (!vpnPortService.exists(VpnPortId.vpnPortId(ifaceId))) {
                continue;
            }

            VpnPort vpnPort = vpnPortService
                    .getPort(VpnPortId.vpnPortId(ifaceId));
            VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();

            VpnInstance vpnInstance = vpnInstanceService
                    .getInstance(vpnInstanceId);

            List<VpnRouteTarget> expRt = route.exportRouteTarget();
            List<VpnRouteTarget> similar = new LinkedList<>(expRt);
            similar.retainAll(vpnInstance.getImportRouteTargets());
            //TODO: currently checking for RT comparision.
            //TODO: Need to check about RD comparision is really required.
            //if (route.routeDistinguisher()
            //.equals(vpnInstance.routeDistinguisher())) {
            if (!similar.isEmpty()) {
                vpnHosts.add(h);
            }
        }
        return vpnHosts;
    }

    private ForwardingObjective.Builder getMplsOutBuilder(DeviceId deviceId,
                                                          EvpnRoute route,
                                                          Host h) {
        DriverHandler handler = driverService.createHandler(deviceId);
        ExtensionTreatmentResolver resolver = handler
                .behaviour(ExtensionTreatmentResolver.class);
        ExtensionTreatment treatment = resolver
                .getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
        try {
            treatment.setPropertyValue(TUNNEL_DST, route.ipNextHop());
        } catch (Exception e) {
            log.error(FAILED_TO_SET_TUNNEL_DST, deviceId);
        }
        TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
        builder.extension(treatment, deviceId);
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchInPort(h.location().port()).matchEthSrc(h.mac())
                .matchEthDst(route.prefixMac()).build();

        TrafficTreatment build = builder.pushMpls()
                .setMpls(MplsLabel.mplsLabel(route.label().getLabel()))
                .setOutput(getTunnlePort(deviceId)).build();

        return DefaultForwardingObjective
                .builder().withTreatment(build).withSelector(selector)
                .fromApp(appId).withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withPriority(60000);

    }

    private ForwardingObjective.Builder getMplsInBuilder(DeviceId deviceId,
                                                         Host host,
                                                         Label label) {
        TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchInPort(getTunnlePort(deviceId))
                .matchEthType(EthType.EtherType.MPLS_UNICAST.ethType()
                                      .toShort())
                .matchMplsBos(true)
                .matchMplsLabel(MplsLabel.mplsLabel(label.getLabel())).build();
        TrafficTreatment treatment = builder.popMpls(EthType
                                                             .EtherType
                                                             .IPV4.ethType())
                .setOutput(host.location().port()).build();
        return DefaultForwardingObjective
                .builder().withTreatment(treatment).withSelector(selector)
                .fromApp(appId).withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withPriority(60000);
    }

    /**
     * Get local tunnel ports.
     *
     * @param ports Iterable of Port
     * @return Collection of PortNumber
     */
    private Collection<PortNumber> getLocalTunnelPorts(Iterable<Port>
                                                               ports) {
        Collection<PortNumber> localTunnelPorts = new ArrayList<>();
        if (ports != null) {
            log.info("port value is not null {}", ports);
            Sets.newHashSet(ports).stream()
                    .filter(p -> !p.number().equals(PortNumber.LOCAL))
                    .forEach(p -> {
                        log.info("number is not matched but no vxlan port");
                        if (p.annotations().value(AnnotationKeys.PORT_NAME)
                                .startsWith(VXLAN)) {
                            localTunnelPorts.add(p.number());
                        }
                    });
        }
        return localTunnelPorts;
    }

    private PortNumber getTunnlePort(DeviceId deviceId) {
        Iterable<Port> ports = deviceService.getPorts(deviceId);
        Collection<PortNumber> localTunnelPorts = getLocalTunnelPorts(ports);
        if (localTunnelPorts.isEmpty()) {
            log.error(CANNOT_FIND_TUNNEL_PORT_DEVICE, deviceId);
            return null;
        }
        return localTunnelPorts.iterator().next();
    }

    private void setFlows(DeviceId deviceId, Host host, Label label,
                          List<VpnRouteTarget> rtImport,
                          Operation type) {
        log.info("Set the flows to OVS");
        ForwardingObjective.Builder objective = getMplsInBuilder(deviceId,
                                                                 host,
                                                                 label);
        if (type.equals(Objective.Operation.ADD)) {
            flowObjectiveService.forward(deviceId, objective.add());
        } else {
            flowObjectiveService.forward(deviceId, objective.remove());
        }

        // download remote flows if and only routes are present.
        evpnRouteStore.getRouteTables().forEach(routeTableId -> {
            Collection<EvpnRouteSet> routes
                    = evpnRouteStore.getRoutes(routeTableId);
            if (routes != null) {
                routes.forEach(route -> {
                    Collection<EvpnRoute> evpnRoutes = route.routes();
                    for (EvpnRoute evpnRoute : evpnRoutes) {
                        EvpnRoute evpnRouteTem = evpnRoute;
                        Set<Host> hostByMac = hostService
                                .getHostsByMac(evpnRouteTem
                                                       .prefixMac());

                        if (!hostByMac.isEmpty()
                                || (!(compareLists(rtImport, evpnRouteTem
                                .exportRouteTarget())))) {
                            log.info("Route target import/export is not matched");
                            continue;
                        }
                        log.info("Set the ARP flows");
                        addArpFlows(deviceId, evpnRouteTem, type, host);
                        ForwardingObjective.Builder build = getMplsOutBuilder(deviceId,
                                                                              evpnRouteTem,
                                                                              host);
                        log.info("Set the MPLS  flows");
                        if (type.equals(Objective.Operation.ADD)) {
                            flowObjectiveService.forward(deviceId, build.add());
                        } else {
                            flowObjectiveService.forward(deviceId, build.remove());
                        }
                    }
                });
            }
        });
    }

    /**
     * comparison for tow lists.
     *
     * @param list1 import list
     * @param list2 export list
     * @return true or false
     */
    public static boolean compareLists(List<VpnRouteTarget> list1,
                                       List<VpnRouteTarget> list2) {
        if (list1 == null && list2 == null) {
            return true;
        }

        if (list1 != null && list2 != null) {
            if (list1.size() == list2.size()) {
                for (VpnRouteTarget li1Long : list1) {
                    boolean isEqual = false;
                    for (VpnRouteTarget li2Long : list2) {
                        if (li1Long.equals(li2Long)) {
                            isEqual = true;
                            break;
                        }
                    }
                    if (!isEqual) {
                        return false;
                    }
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }

    @Override
    public void onHostDetected(Host host) {
        log.info(HOST_DETECT, host);
        DeviceId deviceId = host.location().deviceId();
        if (!mastershipService.isLocalMaster(deviceId)) {
            log.info(NOT_MASTER_FOR_SPECIFIC_DEVICE);
            return;
        }

        String ifaceId = host.annotations().value(IFACEID);
        if (ifaceId == null) {
            log.error(IFACEID_OF_HOST_IS_NULL);
            return;
        }
        VpnPortId vpnPortId = VpnPortId.vpnPortId(ifaceId);
        // Get VPN port id from EVPN app store
        if (!vpnPortService.exists(vpnPortId)) {
            log.info(CANT_FIND_VPN_PORT, ifaceId);
            return;
        }

        VpnPort vpnPort = vpnPortService.getPort(vpnPortId);
        VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
        if (!vpnInstanceService.exists(vpnInstanceId)) {
            log.info(CANT_FIND_VPN_INSTANCE, vpnInstanceId);
            return;
        }

        Label privateLabel = applyLabel();
        // create private route and get label
        setPrivateRoute(host, vpnInstanceId, privateLabel,
                        Objective.Operation.ADD);
        VpnInstance vpnInstance = vpnInstanceService.getInstance(vpnInstanceId);

        List<VpnRouteTarget> rtImport
                = new LinkedList<>(vpnInstance.getImportRouteTargets());
        List<VpnRouteTarget> rtExport
                = new LinkedList<>(vpnInstance.getExportRouteTargets());
        //download flows
        setFlows(deviceId, host, privateLabel, rtImport,
                 Objective.Operation.ADD);
    }

    /**
     * update or withdraw evpn route from route admin service.
     *
     * @param host          host
     * @param vpnInstanceId vpn instance id
     * @param privateLabel  private label
     * @param type          operation type
     */
    private void setPrivateRoute(Host host, VpnInstanceId vpnInstanceId,
                                 Label privateLabel,
                                 Operation type) {
        DeviceId deviceId = host.location().deviceId();
        Device device = deviceService.getDevice(deviceId);
        VpnInstance vpnInstance = vpnInstanceService.getInstance(vpnInstanceId);
        RouteDistinguisher rd = vpnInstance.routeDistinguisher();
        Set<VpnRouteTarget> importRouteTargets
                = vpnInstance.getImportRouteTargets();
        Set<VpnRouteTarget> exportRouteTargets
                = vpnInstance.getExportRouteTargets();
        EvpnInstanceName instanceName = vpnInstance.vpnInstanceName();
        String url = device.annotations().value(SWITCH_CHANNEL_ID);
        String controllerIp = url.substring(0, url.lastIndexOf(":"));

        if (controllerIp == null) {
            log.error(CANT_FIND_CONTROLLER_DEVICE, device.id().toString());
            return;
        }
        IpAddress ipAddress = IpAddress.valueOf(controllerIp);
        // create private route
        EvpnInstanceNextHop evpnNextHop = EvpnInstanceNextHop
                .evpnNextHop(ipAddress, privateLabel);
        EvpnInstancePrefix evpnPrefix = EvpnInstancePrefix
                .evpnPrefix(host.mac(), IpPrefix.valueOf(host.ipAddresses()
                                                                 .iterator()
                                                                 .next()
                                                                 .getIp4Address(), 32));
        EvpnInstanceRoute evpnPrivateRoute
                = new EvpnInstanceRoute(instanceName,
                                        rd,
                                        new LinkedList<>(importRouteTargets),
                                        new LinkedList<>(exportRouteTargets),
                                        evpnPrefix,
                                        evpnNextHop,
                                        IpPrefix.valueOf(host.ipAddresses()
                                                                 .iterator()
                                                                 .next()
                                                                 .getIp4Address(), 32),
                                        ipAddress,
                                        privateLabel);

        // change to public route
        EvpnRoute evpnRoute
                = new EvpnRoute(Source.LOCAL,
                                host.mac(),
                                IpPrefix.valueOf(host.ipAddresses()
                                                         .iterator()
                                                         .next()
                                                         .getIp4Address(), 32),
                                ipAddress,
                                rd,
                                new LinkedList<>(importRouteTargets),
                                new LinkedList<>(exportRouteTargets),
                                privateLabel);
        if (type.equals(Objective.Operation.ADD)) {
            //evpnRouteAdminService.update(Sets.newHashSet(evpnPrivateRoute));
            evpnInstanceRoutes.add(evpnPrivateRoute);
            evpnRouteAdminService.update(Sets.newHashSet(evpnRoute));

        } else {
            //evpnRouteAdminService.withdraw(Sets.newHashSet(evpnPrivateRoute));
            evpnInstanceRoutes.remove(evpnPrivateRoute);
            evpnRouteAdminService.withdraw(Sets.newHashSet(evpnRoute));
        }
    }

    /**
     * Generate the label for evpn route from global pool.
     */
    private Label applyLabel() {
        Collection<LabelResource> privateLabels = labelService
                .applyFromGlobalPool(1);
        Label privateLabel = Label.label(0);
        if (!privateLabels.isEmpty()) {
            privateLabel = Label.label(Integer.parseInt(
                    privateLabels.iterator().next()
                            .labelResourceId().toString()));
        }
        log.info(GET_PRIVATE_LABEL, privateLabel);
        return privateLabel;
    }

    @Override
    public void onHostVanished(Host host) {
        log.info(HOST_VANISHED, host);
        DeviceId deviceId = host.location().deviceId();
        if (!mastershipService.isLocalMaster(deviceId)) {
            return;
        }
        String ifaceId = host.annotations().value(IFACEID);
        if (ifaceId == null) {
            log.error(IFACEID_OF_HOST_IS_NULL);
            return;
        }
        // Get info from Gluon Shim
        VpnPort vpnPort = vpnPortService.getPort(VpnPortId.vpnPortId(ifaceId));
        VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
        if (!vpnInstanceService.exists(vpnInstanceId)) {
            log.info(CANT_FIND_VPN_INSTANCE, vpnInstanceId);
            return;
        }
        VpnInstance vpnInstance = vpnInstanceService.getInstance(vpnInstanceId);

        Label label = releaseLabel(vpnInstance, host);
        // create private route and get label
        setPrivateRoute(host, vpnInstanceId, label, Objective.Operation.REMOVE);
        // download flows
        List<VpnRouteTarget> rtImport
                = new LinkedList<>(vpnInstance.getImportRouteTargets());
        List<VpnRouteTarget> rtExport
                = new LinkedList<>(vpnInstance.getExportRouteTargets());
        setFlows(deviceId, host, label, rtImport,
                 Objective.Operation.REMOVE);
    }

    /**
     * Release the label from the evpn route.
     *
     * @param vpnInstance vpn instance
     * @param host        host
     */
    private Label releaseLabel(VpnInstance vpnInstance, Host host) {
        EvpnInstanceName instanceName = vpnInstance.vpnInstanceName();

        //Get all vpn-instance routes and check for label.
        Label label = null;
        for (EvpnInstanceRoute evpnInstanceRoute : evpnInstanceRoutes) {
            if (evpnInstanceRoute.evpnInstanceName().equals(instanceName)) {
                label = evpnInstanceRoute.getLabel();
                // delete private route and get label ,change to public route
                boolean isRelease
                        = labelService
                        .releaseToGlobalPool(
                                Sets.newHashSet(
                                        LabelResourceId
                                                .labelResourceId(label.getLabel())));
                if (!isRelease) {
                    log.error(RELEASE_LABEL_FAILED, label.getLabel());
                }
                break;
            }
        }
        return label;
    }

    private class InternalRouteEventListener implements EvpnRouteListener {

        @Override
        public void event(EvpnRouteEvent event) {
            if (!(event.subject() instanceof EvpnRoute)) {
                return;
            }
            EvpnRoute route = (EvpnRoute) event.subject();
            if (EvpnRouteEvent.Type.ROUTE_ADDED == event.type()) {
                onBgpEvpnRouteUpdate(route);
            } else if (EvpnRouteEvent.Type.ROUTE_REMOVED == event.type()) {
                onBgpEvpnRouteDelete(route);
            }
        }
    }

    private class InnerHostListener implements HostListener {

        @Override
        public void event(HostEvent event) {
            Host host = event.subject();
            if (HostEvent.Type.HOST_ADDED == event.type()) {
                onHostDetected(host);
            } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
                onHostVanished(host);
            }
        }

    }

    private class InnerVpnPortListener implements VpnPortListener {

        @Override
        public void event(VpnPortEvent event) {
            VpnPort vpnPort = event.subject();
            if (VpnPortEvent.Type.VPN_PORT_DELETE == event.type()) {
                onVpnPortDelete(vpnPort);
            } else if (VpnPortEvent.Type.VPN_PORT_SET == event.type()) {
                onVpnPortSet(vpnPort);
            }
        }
    }

    @Override
    public void onVpnPortDelete(VpnPort vpnPort) {
        // delete the flows of this vpn
        hostService.getHosts().forEach(host -> {
            VpnPortId vpnPortId = vpnPort.id();
            VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
            if (!vpnInstanceService.exists(vpnInstanceId)) {
                log.error(CANT_FIND_VPN_INSTANCE, vpnInstanceId);
                return;
            }
            VpnInstance vpnInstance = vpnInstanceService
                    .getInstance(vpnInstanceId);
            List<VpnRouteTarget> rtImport
                    = new LinkedList<>(vpnInstance.getImportRouteTargets());
            List<VpnRouteTarget> rtExport
                    = new LinkedList<>(vpnInstance.getExportRouteTargets());

            if (vpnPortId.vpnPortId()
                    .equals(host.annotations().value(IFACEID))) {
                log.info(VPN_PORT_UNBIND);
                Label label = releaseLabel(vpnInstance, host);
                // create private route and get label
                DeviceId deviceId = host.location().deviceId();
                setPrivateRoute(host, vpnInstanceId, label,
                                Objective.Operation.REMOVE);
                // download flows
                setFlows(deviceId, host, label, rtImport,
                         Objective.Operation.REMOVE);
            }
        });
    }

    @Override
    public void onVpnPortSet(VpnPort vpnPort) {
        // delete the flows of this vpn
        hostService.getHosts().forEach(host -> {
            VpnPortId vpnPortId = vpnPort.id();
            VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
            VpnInstance vpnInstance = vpnInstanceService
                    .getInstance(vpnInstanceId);
            if (vpnInstance == null) {
                log.info("why vpn instance is null");
                return;
            }
            List<VpnRouteTarget> rtImport
                    = new LinkedList<>(vpnInstance.getImportRouteTargets());
/*            List<VpnRouteTarget> rtExport
                    = new LinkedList<>(vpnInstance.getExportRouteTargets());*/

            if (!vpnInstanceService.exists(vpnInstanceId)) {
                log.error(CANT_FIND_VPN_INSTANCE, vpnInstanceId);
                return;
            }

            if (vpnPortId.vpnPortId()
                    .equals(host.annotations().value(IFACEID))) {
                log.info(VPN_PORT_BIND);
                Label label = applyLabel();
                // create private route and get label
                DeviceId deviceId = host.location().deviceId();
                setPrivateRoute(host, vpnInstanceId, label,
                                Objective.Operation.ADD);
                // download flows
                setFlows(deviceId, host, label, rtImport,
                         Objective.Operation.ADD);
            }
        });
    }

    /**
     * process the gluon configuration and will update the configuration into
     * vpn port service.
     *
     * @param action action
     * @param key    key
     * @param value  json node
     */
    private void processEtcdResponse(String action, String key, JsonNode
            value) {
        String[] list = key.split(SLASH);
        String target = list[list.length - 2];
        switch (target) {
            case VPN_INSTANCE_TARGET:
                VpnInstanceService vpnInstanceService
                        = DefaultServiceDirectory
                        .getService(VpnInstanceService.class);
                vpnInstanceService.processGluonConfig(action, key, value);
                break;
            case VPN_PORT_TARGET:
                VpnPortService vpnPortService = DefaultServiceDirectory
                        .getService(VpnPortService.class);
                vpnPortService.processGluonConfig(action, key, value);
                break;
            case VPN_AF_TARGET:
                VpnAfConfigService vpnAfConfigService =
                        DefaultServiceDirectory.getService(VpnAfConfigService
                                                                   .class);
                vpnAfConfigService.processGluonConfig(action, key, value);
                break;
            case BASEPORT:
                BasePortService basePortService =
                        DefaultServiceDirectory.getService(BasePortService
                                                                   .class);
                basePortService.processGluonConfig(action, key, value);
                break;
            default:
                log.info("why target type is invalid {}", target);
                log.info(INVALID_TARGET_RECEIVED);
                break;
        }
    }

    /**
     * parse the gluon configuration received from network config system.
     *
     * @param jsonNode json node
     * @param key      key
     * @param action   action
     */
    private void parseEtcdResponse(JsonNode jsonNode,
                                   String key,
                                   String action) {
        JsonNode modifyValue = null;
        if (action.equals(SET)) {
            modifyValue = jsonNode.get(key);
        }
        processEtcdResponse(action, key, modifyValue);
    }

    /**
     * Listener for network config events.
     */
    private class InternalNetworkConfigListener implements
            NetworkConfigListener {

        @Override
        public void event(NetworkConfigEvent event) {
            String subject;
            log.info(NETWORK_CONFIG_EVENT_IS_RECEIVED, event.type());
            if (!event.configClass().equals(GluonConfig.class)) {
                return;
            }
            log.info("Event is received from network configuration {}", event
                    .type());
            switch (event.type()) {
                case CONFIG_UPDATED:
                    subject = (String) event.subject();
                    GluonConfig gluonConfig = configService
                            .getConfig(subject, GluonConfig.class);
                    JsonNode jsonNode = gluonConfig.node();
                    parseEtcdResponse(jsonNode, subject, SET);
                    break;
                case CONFIG_REMOVED:
                    subject = (String) event.subject();
                    parseEtcdResponse(null, subject, DELETE);
                    break;
                default:
                    log.info(INVALID_EVENT_RECEIVED);
                    break;
            }
        }
    }

    /**
     * update import and export route target information in route admin service.
     *
     * @param evpnInstanceName   evpn instance name
     * @param exportRouteTargets export route targets
     * @param importRouteTargets import route targets
     * @param action             action holds update or delete
     */
    private void updateImpExpRtInRoute(EvpnInstanceName evpnInstanceName,
                                       Set<VpnRouteTarget> exportRouteTargets,
                                       Set<VpnRouteTarget> importRouteTargets,
                                       String action) {

        for (EvpnInstanceRoute evpnInstanceRoute : evpnInstanceRoutes) {
            if (evpnInstanceRoute.evpnInstanceName().equals(evpnInstanceName)) {
                evpnInstanceRoute
                        .setExportRtList(new LinkedList<>(exportRouteTargets));
                evpnInstanceRoute
                        .setImportRtList(new LinkedList<>(importRouteTargets));
                if (action.equals(UPDATE)) {
                    evpnInstanceRoutes.add(evpnInstanceRoute);
                } else if (action.equals(DELETE)) {
                    evpnInstanceRoutes.remove(evpnInstanceRoute);
                }
                //Get the public route and update route targets.
                EvpnNextHop evpnNextHop = EvpnNextHop
                        .evpnNextHop(evpnInstanceRoute.getNextHopl(),
                                     evpnInstanceRoute.importRouteTarget(),
                                     evpnInstanceRoute.exportRouteTarget(),
                                     evpnInstanceRoute.getLabel());
                Collection<EvpnRoute> evpnPublicRoutes
                        = evpnRouteStore.getRoutesForNextHop(evpnNextHop.nextHop());
                for (EvpnRoute pubRoute : evpnPublicRoutes) {
                    EvpnRoute evpnPubRoute = pubRoute;
                    if (evpnPubRoute.label().equals(evpnInstanceRoute
                                                            .getLabel())) {
                        evpnPubRoute
                                .setExportRtList(new LinkedList<>(exportRouteTargets));
                        evpnPubRoute
                                .setImportRtList(new LinkedList<>(importRouteTargets));
                        if (action.equals(UPDATE)) {
                            evpnRouteAdminService.update(Sets.newHashSet(evpnPubRoute));
                        } else if (action.equals(DELETE)) {
                            evpnRouteAdminService
                                    .withdraw(Sets.newHashSet(evpnPubRoute));
                        }
                    }
                }
            }
        }
    }

    /**
     * update or withdraw evpn route based on vpn af configuration.
     *
     * @param vpnAfConfig vpn af configuration
     * @param action      action holds update or delete
     */

    private void processEvpnRouteUpdate(VpnAfConfig vpnAfConfig,
                                        String action) {
        Collection<VpnInstance> instances
                = vpnInstanceService.getInstances();
        for (VpnInstance vpnInstance : instances) {
            Set<VpnRouteTarget> configRouteTargets
                    = vpnInstance.getConfigRouteTargets();
            for (VpnRouteTarget vpnRouteTarget : configRouteTargets) {
                if (vpnRouteTarget.equals(vpnAfConfig.routeTarget())) {
                    Set<VpnRouteTarget> exportRouteTargets
                            = vpnInstance.getExportRouteTargets();
                    Set<VpnRouteTarget> importRouteTargets
                            = vpnInstance.getImportRouteTargets();
                    String routeTargetType = vpnAfConfig.routeTargetType();
                    if (action.equals(UPDATE)) {
                        vpnInstanceService
                                .updateImpExpRouteTargets(routeTargetType,
                                                          exportRouteTargets,
                                                          importRouteTargets,
                                                          vpnRouteTarget);
                    } else if (action.equals(DELETE)) {
                        switch (routeTargetType) {
                            case EXPORT_EXTCOMMUNITY:
                                exportRouteTargets.remove(vpnRouteTarget);
                                break;
                            case IMPORT_EXTCOMMUNITY:
                                importRouteTargets.remove(vpnRouteTarget);
                                break;
                            case BOTH:
                                exportRouteTargets.remove(vpnRouteTarget);
                                importRouteTargets.remove(vpnRouteTarget);
                                break;
                            default:
                                log.info(INVALID_ROUTE_TARGET_TYPE);
                                break;
                        }
                    }
                    updateImpExpRtInRoute(vpnInstance.vpnInstanceName(),
                                          exportRouteTargets,
                                          importRouteTargets,
                                          action);
                }
            }
        }
    }

    private class InnerVpnAfConfigListener implements VpnAfConfigListener {

        @Override
        public void event(VpnAfConfigEvent event) {
            VpnAfConfig vpnAfConfig = event.subject();
            if (VpnAfConfigEvent.Type.VPN_AF_CONFIG_DELETE == event.type()) {
                processEvpnRouteUpdate(vpnAfConfig, DELETE);
            } else if (VpnAfConfigEvent.Type.VPN_AF_CONFIG_SET
                    == event.type() || VpnAfConfigEvent.Type
                    .VPN_AF_CONFIG_UPDATE == event.type()) {
                processEvpnRouteUpdate(vpnAfConfig, UPDATE);
            }
        }
    }
}
