/*
 * Copyright 2016-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.incubator.net.virtual.impl.provider;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
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.Modified;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
import org.onosproject.incubator.net.virtual.provider.InternalRoutingAlgorithm;
import org.onosproject.incubator.net.virtual.provider.VirtualFlowRuleProvider;
import org.onosproject.incubator.net.virtual.provider.VirtualFlowRuleProviderService;
import org.onosproject.incubator.net.virtual.provider.VirtualProviderRegistryService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.BatchOperationEntry;
import org.onosproject.net.flow.CompletedBatchOperation;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleOperations;
import org.onosproject.net.flow.FlowRuleOperationsContext;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.TopologyService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

import java.util.Dictionary;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableSet.copyOf;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Provider that translate virtual flow rules into physical rules.
 * Current implementation is based on FlowRules.
 * This virtualize and de-virtualize virtual flow rules into physical flow rules.
 * {@link org.onosproject.net.flow.FlowRule}
 */
@Component(immediate = true)
@Service
public class DefaultVirtualFlowRuleProvider extends AbstractVirtualProvider
        implements VirtualFlowRuleProvider {

    private static final String APP_ID_STR = "org.onosproject.virtual.vnet-flow_";

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected TopologyService topologyService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VirtualNetworkService vnService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowRuleService flowRuleService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VirtualProviderRegistryService providerRegistryService;

    private InternalRoutingAlgorithm internalRoutingAlgorithm;
    private InternalVirtualFlowRuleManager frm;
    private ApplicationId appId;
    private FlowRuleListener flowRuleListener;

    /**
     * Creates a provider with the identifier.
     */
    public DefaultVirtualFlowRuleProvider() {
        super(new ProviderId("vnet-flow", "org.onosproject.virtual.vnet-flow"));
    }

    @Activate
    public void activate() {
        appId = coreService.registerApplication(APP_ID_STR);

        providerRegistryService.registerProvider(this);

        flowRuleListener = new InternalFlowRuleListener();
        flowRuleService.addListener(flowRuleListener);

        internalRoutingAlgorithm = new DefaultInternalRoutingAlgorithm();
        frm = new InternalVirtualFlowRuleManager();

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        flowRuleService.removeListener(flowRuleListener);
        flowRuleService.removeFlowRulesById(appId);
        providerRegistryService.unregisterProvider(this);
        log.info("Stopped");
    }

    @Modified
    protected void modified(ComponentContext context) {
        Dictionary<?, ?> properties = context.getProperties();
    }

    @Override
    public void applyFlowRule(NetworkId networkId, FlowRule... flowRules) {
        for (FlowRule flowRule : flowRules) {
            devirtualize(networkId, flowRule).forEach(
                    r -> flowRuleService.applyFlowRules(r));
        }
    }

    @Override
    public void removeFlowRule(NetworkId networkId, FlowRule... flowRules) {
        for (FlowRule flowRule : flowRules) {
            devirtualize(networkId, flowRule).forEach(
                    r -> flowRuleService.removeFlowRules(r));
        }
    }

    @Override
    public void executeBatch(NetworkId networkId, FlowRuleBatchOperation batch) {
        checkNotNull(batch);

        for (FlowRuleBatchEntry fop : batch.getOperations()) {
            FlowRuleOperations.Builder builder = FlowRuleOperations.builder();

            switch (fop.operator()) {
                case ADD:
                    devirtualize(networkId, fop.target()).forEach(builder::add);
                    break;
                case REMOVE:
                    devirtualize(networkId, fop.target()).forEach(builder::remove);
                    break;
                case MODIFY:
                    devirtualize(networkId, fop.target()).forEach(builder::modify);
                    break;
                default:
                    break;
            }

            flowRuleService.apply(builder.build(new FlowRuleOperationsContext() {
                @Override
                public void onSuccess(FlowRuleOperations ops) {
                    CompletedBatchOperation status =
                            new CompletedBatchOperation(true,
                                                        Sets.newConcurrentHashSet(),
                                                        batch.deviceId());

                    VirtualFlowRuleProviderService providerService =
                            (VirtualFlowRuleProviderService) providerRegistryService
                                    .getProviderService(networkId,
                                                        VirtualFlowRuleProvider.class);
                    providerService.batchOperationCompleted(batch.id(), status);
                }

                @Override
                public void onError(FlowRuleOperations ops) {
                    Set<FlowRule> failures = ImmutableSet.copyOf(
                            Lists.transform(batch.getOperations(),
                                            BatchOperationEntry::target));

                    CompletedBatchOperation status =
                            new CompletedBatchOperation(false,
                                                        failures,
                                                        batch.deviceId());

                    VirtualFlowRuleProviderService providerService =
                            (VirtualFlowRuleProviderService) providerRegistryService
                                    .getProviderService(networkId,
                                                        VirtualFlowRuleProvider.class);
                    providerService.batchOperationCompleted(batch.id(), status);
                }
            }));
        }
    }

    public void setEmbeddingAlgorithm(InternalRoutingAlgorithm
                                              internalRoutingAlgorithm) {
        this.internalRoutingAlgorithm = internalRoutingAlgorithm;
    }

    /**
     * Translate the requested physical flow rules into virtual flow rules.
     *
     * @param flowRule A virtual flow rule to be translated
     * @return A flow rule for a specific virtual network
     */
    private FlowRule virtualizeFlowRule(FlowRule flowRule) {

        FlowRule storedrule = frm.getVirtualRule(flowRule);

        if (flowRule.reason() == FlowRule.FlowRemoveReason.NO_REASON) {
            return storedrule;
        } else {
            return DefaultFlowRule.builder()
                    .withReason(flowRule.reason())
                    .withPriority(storedrule.priority())
                    .forDevice(storedrule.deviceId())
                    .forTable(storedrule.tableId())
                    .fromApp(new DefaultApplicationId(storedrule.appId(), null))
                    .withIdleTimeout(storedrule.timeout())
                    .withHardTimeout(storedrule.hardTimeout())
                    .withSelector(storedrule.selector())
                    .withTreatment(storedrule.treatment())
                    .build();
        }
    }

    private FlowEntry virtualize(FlowEntry flowEntry) {
        FlowRule vRule = virtualizeFlowRule(flowEntry);

        if (vRule == null) {
            return null;
        }

        FlowEntry vEntry = new DefaultFlowEntry(vRule, flowEntry.state(),
                                                flowEntry.life(),
                                                flowEntry.packets(),
                                                flowEntry.bytes());
        return vEntry;
    }

    /**
     * Translate the requested virtual flow rules into physical flow rules.
     * The translation could be one to many.
     *
     * @param flowRule A flow rule from underlying data plane to be translated
     * @return A set of flow rules for physical network
     */
    private Set<FlowRule> devirtualize(NetworkId networkId, FlowRule flowRule) {

        Set<FlowRule> outRules = new HashSet<>();

        Set<ConnectPoint> ingressPoints = extractIngressPoints(networkId,
                                                               flowRule.deviceId(),
                                                               flowRule.selector());

        ConnectPoint egressPoint = extractEgressPoints(networkId,
                                                         flowRule.deviceId(),
                                                         flowRule.treatment());

        if (egressPoint == null) {
            return outRules;
        }

        TrafficSelector.Builder commonSelectorBuilder
                = DefaultTrafficSelector.builder();
        flowRule.selector().criteria().stream()
                .filter(c -> c.type() != Criterion.Type.IN_PORT)
                .forEach(c -> commonSelectorBuilder.add(c));
        TrafficSelector commonSelector = commonSelectorBuilder.build();

        TrafficTreatment.Builder commonTreatmentBuilder
                = DefaultTrafficTreatment.builder();
        flowRule.treatment().allInstructions().stream()
                .filter(i -> i.type() != Instruction.Type.OUTPUT)
                .forEach(i -> commonTreatmentBuilder.add(i));
        TrafficTreatment commonTreatment = commonTreatmentBuilder.build();

        for (ConnectPoint ingressPoint : ingressPoints) {
            if (egressPoint.port() == PortNumber.FLOOD) {
                Set<ConnectPoint> outPoints = vnService
                        .getVirtualPorts(networkId, flowRule.deviceId())
                        .stream()
                        .map(VirtualPort::realizedBy)
                        .filter(p -> !p.equals(ingressPoint))
                        .collect(Collectors.toSet());

                for (ConnectPoint outPoint : outPoints) {
                    outRules.addAll(generateRules(networkId, ingressPoint, outPoint,
                                                  commonSelector, commonTreatment, flowRule));
                }
            } else {
                outRules.addAll(generateRules(networkId, ingressPoint, egressPoint,
                                              commonSelector, commonTreatment, flowRule));
            }
        }

        return outRules;
    }

    /**
     * Extract ingress connect points of the physical network
     * from the requested traffic selector.
     *
     * @param networkId the virtual network identifier
     * @param deviceId the virtual device identifier
     * @param selector the traffic selector to extract ingress point
     * @return the set of ingress connect points of the physical network
     */
    private Set<ConnectPoint> extractIngressPoints(NetworkId networkId,
                                                   DeviceId deviceId,
                                                   TrafficSelector selector) {

        Set<ConnectPoint> ingressPoints = new HashSet<>();

        Set<VirtualPort> vPorts = vnService
                .getVirtualPorts(networkId, deviceId);

        PortCriterion portCriterion = ((PortCriterion) selector
                .getCriterion(Criterion.Type.IN_PORT));

        if (portCriterion != null) {
            PortNumber vInPortNum = portCriterion.port();

            Optional<ConnectPoint> optionalCp =  vPorts.stream()
                    .filter(v -> v.number().equals(vInPortNum))
                    .map(VirtualPort::realizedBy).findFirst();
            if (!optionalCp.isPresent()) {
                log.warn("Port {} is not realized yet, in Network {}, Device {}",
                         vInPortNum, networkId, deviceId);
                return ingressPoints;
            }

            ingressPoints.add(optionalCp.get());
        } else {
            for (VirtualPort vPort : vPorts) {
                if (vPort.realizedBy() != null) {
                    ingressPoints.add(vPort.realizedBy());
                } else {
                    log.warn("Port {} is not realized yet, in Network {}, " +
                                     "Device {}",
                             vPort, networkId, deviceId);
                }
            }
        }

        return ingressPoints;
    }

    /**
     * Extract egress connect point of the physical network
     * from the requested traffic treatment.
     *
     * @param networkId the virtual network identifier
     * @param deviceId the virtual device identifier
     * @param treatment the traffic treatment to extract ingress point
     * @return the egress connect point of the physical network
     */
    private ConnectPoint extractEgressPoints(NetworkId networkId,
                                                  DeviceId deviceId,
                                                  TrafficTreatment treatment) {

        Set<VirtualPort> vPorts = vnService
                .getVirtualPorts(networkId, deviceId);

        PortNumber vOutPortNum = treatment.allInstructions().stream()
                .filter(i -> i.type() == Instruction.Type.OUTPUT)
                .map(i -> ((Instructions.OutputInstruction) i).port())
                .findFirst().get();

        Optional<ConnectPoint> optionalCpOut = vPorts.stream()
                .filter(v -> v.number().equals(vOutPortNum))
                .map(VirtualPort::realizedBy)
                .findFirst();

        if (!optionalCpOut.isPresent()) {
            if (vOutPortNum.isLogical()) {
                return new ConnectPoint(DeviceId.deviceId("vNet"), vOutPortNum);
            }

            log.warn("Port {} is not realized yet, in Network {}, Device {}",
                     vOutPortNum, networkId, deviceId);
            return null;
        }

        return optionalCpOut.get();
    }


    /**
     * Generates the corresponding flow rules for the physical network.
     *
     * @param networkId The virtual network identifier
     * @param ingressPoint The ingress point of the physical network
     * @param egressPoint The egress point of the physical network
     * @param commonSelector A common traffic selector between the virtual
     *                       and physical flow rules
     * @param commonTreatment A common traffic treatment between the virtual
     *                        and physical flow rules
     * @param flowRule The virtual flow rule to be translated
     * @return A set of flow rules for the physical network
     */
    private Set<FlowRule> generateRules(NetworkId networkId,
                                        ConnectPoint ingressPoint,
                                        ConnectPoint egressPoint,
                                        TrafficSelector commonSelector,
                                        TrafficTreatment commonTreatment,
                                        FlowRule flowRule) {

        if (ingressPoint.deviceId().equals(egressPoint.deviceId()) ||
                egressPoint.port().isLogical()) {
            return generateRuleForSingle(networkId, ingressPoint, egressPoint,
                                         commonSelector, commonTreatment, flowRule);
        } else {
            return generateRuleForMulti(networkId, ingressPoint, egressPoint,
                                         commonSelector, commonTreatment, flowRule);
        }
    }

    /**
     * Generate physical rules when a virtual flow rule can be handled inside
     * a single physical switch.
     *
     * @param networkId The virtual network identifier
     * @param ingressPoint The ingress point of the physical network
     * @param egressPoint The egress point of the physical network
     * @param commonSelector A common traffic selector between the virtual
     *                       and physical flow rules
     * @param commonTreatment A common traffic treatment between the virtual
     *                        and physical flow rules
     * @param flowRule The virtual flow rule to be translated
     * @return A set of flow rules for the physical network
     */
    private Set<FlowRule> generateRuleForSingle(NetworkId networkId,
            ConnectPoint ingressPoint,
            ConnectPoint egressPoint,
            TrafficSelector commonSelector,
            TrafficTreatment commonTreatment,
            FlowRule flowRule) {

        Set<FlowRule> outRules = new HashSet<>();

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector
                .builder(commonSelector)
                .matchInPort(ingressPoint.port());

        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment
                .builder(commonTreatment)
                .setOutput(egressPoint.port());

        FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
                .fromApp(vnService.getVirtualNetworkApplicationId(networkId))
                .forDevice(ingressPoint.deviceId())
                .withSelector(selectorBuilder.build())
                .withTreatment(treatmentBuilder.build())
                .withIdleTimeout(flowRule.timeout())
                .withPriority(flowRule.priority());

        FlowRule rule = ruleBuilder.build();
        frm.addIngressRule(flowRule, rule, networkId);
        outRules.add(rule);

        return outRules;
    }

    /**
     * Generate physical rules when a virtual flow rule can be handled with
     * multiple physical switches.
     *
     * @param networkId The virtual network identifier
     * @param ingressPoint The ingress point of the physical network
     * @param egressPoint The egress point of the physical network
     * @param commonSelector A common traffic selector between the virtual
     *                       and physical flow rules
     * @param commonTreatment A common traffic treatment between the virtual
     *                        and physical flow rules
     * @param flowRule The virtual flow rule to be translated
     * @return A set of flow rules for the physical network
     */
    private Set<FlowRule> generateRuleForMulti(NetworkId networkId,
                                                ConnectPoint ingressPoint,
                                                ConnectPoint egressPoint,
                                                TrafficSelector commonSelector,
                                                TrafficTreatment commonTreatment,
                                                FlowRule flowRule) {
        Set<FlowRule> outRules = new HashSet<>();

        Path internalPath = internalRoutingAlgorithm
                .findPath(ingressPoint, egressPoint);
        checkNotNull(internalPath, "No path between " +
                ingressPoint.toString() + " " + egressPoint.toString());

        ConnectPoint outCp = internalPath.links().get(0).src();

        //ingress point of tunnel
        TrafficSelector.Builder selectorBuilder =
                DefaultTrafficSelector.builder(commonSelector);
        selectorBuilder.matchInPort(ingressPoint.port());

        TrafficTreatment.Builder treatmentBuilder =
                DefaultTrafficTreatment.builder(commonTreatment);
        //TODO: add the logic to check host location
        treatmentBuilder.pushVlan()
                .setVlanId(VlanId.vlanId(networkId.id().shortValue()));
        treatmentBuilder.setOutput(outCp.port());

        FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
                .fromApp(vnService.getVirtualNetworkApplicationId(networkId))
                .forDevice(ingressPoint.deviceId())
                .withSelector(selectorBuilder.build())
                .withIdleTimeout(flowRule.timeout())
                .withTreatment(treatmentBuilder.build())
                .withPriority(flowRule.priority());

        FlowRule rule = ruleBuilder.build();
        frm.addIngressRule(flowRule, rule, networkId);
        outRules.add(rule);

        //routing inside tunnel
        ConnectPoint inCp = internalPath.links().get(0).dst();

        if (internalPath.links().size() > 1) {
            for (Link l : internalPath.links()
                    .subList(1, internalPath.links().size())) {

                outCp = l.src();

                selectorBuilder = DefaultTrafficSelector
                        .builder(commonSelector)
                        .matchVlanId(VlanId.vlanId(networkId.id().shortValue()))
                        .matchInPort(inCp.port());

                treatmentBuilder = DefaultTrafficTreatment
                        .builder(commonTreatment)
                        .setOutput(outCp.port());

                ruleBuilder = DefaultFlowRule.builder()
                        .fromApp(vnService.getVirtualNetworkApplicationId(networkId))
                        .forDevice(inCp.deviceId())
                        .withSelector(selectorBuilder.build())
                        .withTreatment(treatmentBuilder.build())
                        .withIdleTimeout(flowRule.timeout())
                        .withPriority(flowRule.priority());

                outRules.add(ruleBuilder.build());
                inCp = l.dst();
            }
        }

        //egress point of tunnel
        selectorBuilder = DefaultTrafficSelector.builder(commonSelector)
                .matchVlanId(VlanId.vlanId(networkId.id().shortValue()))
                .matchInPort(inCp.port());

        treatmentBuilder = DefaultTrafficTreatment.builder(commonTreatment)
                .popVlan()
                .setOutput(egressPoint.port());

        ruleBuilder = DefaultFlowRule.builder()
                .fromApp(appId)
                .forDevice(egressPoint.deviceId())
                .withSelector(selectorBuilder.build())
                .withTreatment(treatmentBuilder.build())
                .withIdleTimeout(flowRule.timeout())
                .withPriority(flowRule.priority());

        outRules.add(ruleBuilder.build());

        return outRules;
    }

    private class InternalFlowRuleListener implements FlowRuleListener {
        @Override
        public void event(FlowRuleEvent event) {
            if ((event.type() == FlowRuleEvent.Type.RULE_ADDED) ||
                    (event.type() == FlowRuleEvent.Type.RULE_UPDATED)) {
                if (frm.isVirtualIngressRule(event.subject())) {
                    NetworkId networkId = frm.getVirtualNetworkId(event.subject());
                    FlowEntry vEntry = getVirtualFlowEntry(event.subject());

                    if (vEntry == null) {
                        return;
                    }

                    frm.addOrUpdateFlowEntry(networkId, vEntry.deviceId(), vEntry);

                    VirtualFlowRuleProviderService providerService =
                            (VirtualFlowRuleProviderService) providerRegistryService
                                    .getProviderService(networkId,
                                                        VirtualFlowRuleProvider.class);

                    ImmutableList.Builder<FlowEntry> builder = ImmutableList.builder();
                    builder.addAll(frm.getFlowEntries(networkId, vEntry.deviceId()));

                    providerService.pushFlowMetrics(vEntry.deviceId(), builder.build());
                }
            } else if (event.type() == FlowRuleEvent.Type.RULE_REMOVED) {
                if (frm.isVirtualIngressRule(event.subject())) {
                    //FIXME confirm all physical rules are removed
                    NetworkId networkId = frm.getVirtualNetworkId(event.subject());
                    FlowEntry vEntry = getVirtualFlowEntry(event.subject());

                    if (vEntry == null) {
                        return;
                    }

                    frm.removeFlowEntry(networkId, vEntry.deviceId(), vEntry);
                    frm.removeFlowRule(networkId, vEntry.deviceId(), vEntry);

                    VirtualFlowRuleProviderService providerService =
                            (VirtualFlowRuleProviderService) providerRegistryService
                                    .getProviderService(networkId,
                                                        VirtualFlowRuleProvider.class);
                    providerService.flowRemoved(vEntry);
                }
            }
        }

        private FlowEntry getVirtualFlowEntry(FlowRule rule) {
            FlowEntry entry = null;
            for (FlowEntry fe :
                    flowRuleService.getFlowEntries(rule.deviceId())) {
                if (rule.exactMatch(fe)) {
                    entry = fe;
                }
            }

            if (entry != null) {
                return virtualize(entry);
            } else  {
                return virtualize(new DefaultFlowEntry(rule,
                                                       FlowEntry.FlowEntryState.PENDING_REMOVE));
            }
        }
    }

    private class InternalVirtualFlowRuleManager {
        /** <Virtual Network ID, Virtual Device ID, Virtual Flow Rules>.*/
        final Table<NetworkId, DeviceId, Set<FlowRule>> flowRuleTable
                = HashBasedTable.create();

        /** <Virtual Network ID, Virtual Device ID, Virtual Flow Entries>.*/
        final Table<NetworkId, DeviceId, Set<FlowEntry>> flowEntryTable
                = HashBasedTable.create();

        /** <Physical Flow Rule, Virtual Network ID>.*/
        final Map<FlowRule, NetworkId> ingressRuleMap = Maps.newHashMap();

        /** <Physical Flow Rule, Virtual Virtual Flow Rule>.*/
        final Map<FlowRule, FlowRule> virtualizationMap = Maps.newHashMap();

        private Iterable<FlowRule> getFlowRules(NetworkId networkId,
                                                DeviceId deviceId) {
            return flowRuleTable.get(networkId, deviceId);
        }

        private Iterable<FlowEntry> getFlowEntries(NetworkId networkId,
                                                   DeviceId deviceId) {
            return flowEntryTable.get(networkId, deviceId);
        }

        private void addFlowRule(NetworkId networkId, DeviceId deviceId,
                                 FlowRule flowRule) {
            Set<FlowRule> set = flowRuleTable.get(networkId, deviceId);
            if (set == null) {
                set = Sets.newHashSet();
                flowRuleTable.put(networkId, deviceId, set);
            }
            set.add(flowRule);
        }

        private void removeFlowRule(NetworkId networkId, DeviceId deviceId,
                                    FlowRule flowRule) {
            Set<FlowRule> set = flowRuleTable.get(networkId, deviceId);
            if (set == null) {
                return;
            }
            set.remove(flowRule);
        }

        private void addOrUpdateFlowEntry(NetworkId networkId, DeviceId deviceId,
                                  FlowEntry flowEntry) {
            Set<FlowEntry> set = flowEntryTable.get(networkId, deviceId);
            if (set == null) {
                set = Sets.newConcurrentHashSet();
                flowEntryTable.put(networkId, deviceId, set);
            }

            //Replace old entry with new one
            set.stream().filter(fe -> fe.exactMatch(flowEntry))
                    .forEach(set::remove);
            set.add(flowEntry);
        }

        private void removeFlowEntry(NetworkId networkId, DeviceId deviceId,
                                     FlowEntry flowEntry) {
            Set<FlowEntry> set = flowEntryTable.get(networkId, deviceId);
            if (set == null) {
                return;
            }
            set.remove(flowEntry);
        }

        private void addIngressRule(FlowRule virtualRule, FlowRule physicalRule,
                                    NetworkId networkId) {
            ingressRuleMap.put(physicalRule, networkId);
            virtualizationMap.put(physicalRule, virtualRule);
        }

        private FlowRule getVirtualRule(FlowRule physicalRule) {
                return virtualizationMap.get(physicalRule);
        }

        private void removeIngressRule(FlowRule physicalRule) {
            ingressRuleMap.remove(physicalRule);
            virtualizationMap.remove(physicalRule);
        }

        private Set<FlowRule> getAllPhysicalRule() {
            return copyOf(virtualizationMap.keySet());
        }

        private NetworkId getVirtualNetworkId(FlowRule physicalRule) {
            return ingressRuleMap.get(physicalRule);
        }

        /**
         * Test the rule is the ingress rule for virtual rules.
         *
         * @param flowRule A flow rule from underlying data plane to be translated
         * @return True when the rule is for ingress point for a virtual switch
         */
        private boolean isVirtualIngressRule(FlowRule flowRule) {
            return ingressRuleMap.containsKey(flowRule);
        }
    }

    private class DefaultInternalRoutingAlgorithm
            implements InternalRoutingAlgorithm {

        @Override
        public Path findPath(ConnectPoint src, ConnectPoint dst) {
            Set<Path> paths =
                    topologyService.getPaths(topologyService.currentTopology(),
                                             src.deviceId(),
                                             dst.deviceId());

            if (paths.isEmpty()) {
                return null;
            }

            //TODO the logic find the best path
            return (Path) paths.toArray()[0];
        }
    }
}
