/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.drivers.microsemi;

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

import java.math.BigInteger;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;

import org.onlab.packet.EthType;
import org.onlab.packet.EthType.EtherType;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService;
import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
import org.onosproject.drivers.microsemi.yang.UniSide;
import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnic;
import org.onosproject.drivers.microsemi.yang.custom.CustomEvcPerUnin;
import org.onosproject.drivers.microsemi.yang.utils.CeVlanMapUtils;
import org.onosproject.net.PortNumber;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
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.FlowEntry.FlowEntryState;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.Criterion.Type;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanHeaderInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.meter.MeterId;
import org.onosproject.netconf.DatastoreId;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfDevice;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFiltering;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.MseaSaFilteringOpParam;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.DefaultSourceIpaddressFiltering;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.SourceIpaddressFiltering;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.DefaultInterfaceEth0;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.InterfaceEth0;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.DefaultSourceAddressRange;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.FilterAdminStateEnum;
import org.onosproject.yang.gen.v1.mseasafiltering.rev20160412.mseasafiltering.sourceipaddressfiltering.interfaceeth0.SourceAddressRange;
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.ServiceListType;
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.VlanIdType;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcService;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.DefaultFlowMapping;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.FlowMapping;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.TagManipulation;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagOverwrite;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPop;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.DefaultTagPush;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagOverwrite;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPop;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.TagPush;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.evcperuniextensionattributes.tagmanipulation.tagpush.tagpush.PushTagTypeEnum;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultUni;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Uni;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.DefaultEvc;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.Evc;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.UniSideInterfaceAssignmentEnum;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.DefaultEvcPerUni;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.EvcPerUni;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnic;
import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.uni.evc.evcperuni.EvcPerUnin;
import org.slf4j.Logger;

/**
 * An implementation of the FlowRuleProgrammable behaviour for the EA10000 device.
 *
 * This device is not a native Open Flow device. It has only a NETCONF interface for configuration
 * status retrieval and notifications. It supports only a small subset of OpenFlow rules.<br>
 *
 * The device supports only:<br>
 * 1) Open flow rules that blocks certain IP address ranges, but only those incoming on Port 0
 *    and has a limit of 10 such rules<br>
 * 2) Open flow rules that PUSH, POP and OVERWRITE VLAN tags on both ports. This can push and overwrite
 *    both C-TAGs (0x8100) and S-TAGs (0x88a8).
 */
public class EA1000FlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {

    protected final Logger log = getLogger(getClass());
    public static final String MICROSEMI_DRIVERS = "com.microsemi.drivers";
    public static final int PRIORITY_DEFAULT = 50000;
    //To protect the NETCONF session from concurrent access across flow addition and removal
    static Semaphore sessionMutex = new Semaphore(1);

    /**
     * Get the flow entries that are present on the EA1000.
     * Since the EA1000 does not have any 'real' flow entries these are retrieved from 2 configuration
     * areas on the EA1000 NETCONF model - from SA filtering YANG model and from EVC UNI YANG model.<br>
     * The flow entries must match exactly the FlowRule entries in the ONOS store. If they are not an
     * exact match the device will be requested to remove those flows and the FlowRule will stay in a
     * PENDING_ADD state.
     * @return A collection of Flow Entries
     */
    @Override
    public Collection<FlowEntry> getFlowEntries() {
        Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();

        UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
        NetconfDevice ncDevice = controller.getDevicesMap().get(handler().data().deviceId());
        if (ncDevice == null) {
            log.error("Internal ONOS Error. Device has been marked as reachable, " +
                            "but deviceID {} is not in Devices Map. Continuing with empty description",
                    handler().data().deviceId());
            return flowEntryCollection;
        }
        NetconfSession session = ncDevice.getSession();
        CoreService coreService = checkNotNull(handler().get(CoreService.class));
        ApplicationId appId = coreService.getAppId(MICROSEMI_DRIVERS);
        MseaSaFilteringNetconfService mseaSaFilteringService =
                (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
        MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
                (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
        log.debug("getFlowEntries() called on EA1000FlowRuleProgrammable");

        //First get the MseaSaFiltering rules
        SourceIpaddressFiltering sip =
                new DefaultSourceIpaddressFiltering();

        MseaSaFilteringOpParam op =
                new MseaSaFilteringOpParam();
        op.sourceIpaddressFiltering(sip);

        try {
            MseaSaFiltering saFilteringCurrent =
                    mseaSaFilteringService.getMseaSaFiltering(op, session);
            if (saFilteringCurrent != null &&
                    saFilteringCurrent.sourceIpaddressFiltering() != null) {
                flowEntryCollection.addAll(
                        convertSaFilteringToFlowRules(saFilteringCurrent, appId));
            }
        } catch (NetconfException e) {
            if (e.getCause() instanceof TimeoutException) {
                log.warn("Timeout exception getting SA Filt Flow Entries from {}",
                        handler().data().deviceId());
                return flowEntryCollection;
            } else {
                log.error("Unexpected error on SA Filt getFlowEntries on {}",
                        handler().data().deviceId(), e);
                return flowEntryCollection;
            }
        }


        //Then get the EVCs - there will be a flow entry per EVC
        MefServices mefServices = new DefaultMefServices();
        mefServices.uni(new DefaultUni());

        MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
        mseaUniEvcServiceFilter.mefServices(mefServices);
        try {
            MseaUniEvcService uniEvcCurrent =
                    mseaUniEvcServiceSvc.getConfigMseaUniEvcService(mseaUniEvcServiceFilter,
                            session, DatastoreId.RUNNING);

            flowEntryCollection.addAll(
                    convertEvcUniToFlowRules(uniEvcCurrent, portAssignment));

        } catch (NetconfException e) {
            if (e.getCause() instanceof TimeoutException) {
                log.warn("Timeout exception getting EVC Flow Entries from {}",
                        handler().data().deviceId());
                return flowEntryCollection;
            } else {
                log.error("Unexpected error on EVC getFlowEntries on {}",
                        handler().data().deviceId(), e);
            }
        }

        return flowEntryCollection;
    }

    /**
     * Apply the flow entries to the EA1000.
     * Since the EA1000 does not have any 'real' flow entries these are converted 2 configuration
     * areas on the EA1000 NETCONF model - to SA filtering YANG model and to EVC UNI YANG model.<br>
     * Only a subset of the possible OpenFlow rules are supported. Any rule that's not handled
     * will not be in the returned set.
     *
     * @param rules A collection of Flow Rules to be applied to the EA1000
     * @return A collection of the Flow Rules that have been added.
     */
    @Override
    public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
        Collection<FlowRule> frAdded = new HashSet<FlowRule>();
        if (rules == null || rules.size() == 0) {
            return rules;
        }
        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
        MseaSaFilteringNetconfService mseaSaFilteringService =
                (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
        MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
                (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
        log.debug("applyFlowRules() called on EA1000FlowRuleProgrammable with {} rules.", rules.size());
        // FIXME: Change this so it's dynamically driven
        UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;

        List<SourceAddressRange> saRangeList = new ArrayList<SourceAddressRange>();
        Map<Integer, Evc> evcMap = new HashMap<>();

        //Retrieve the list of actual EVCs and the CeVlanMaps from device
        List<Evc> activeEvcs = new ArrayList<>();
        try {
            sessionMutex.acquire();
            MseaUniEvcService evcResponse =
                    mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING);
            //There could be zero or more EVCs
            if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) {
                activeEvcs.addAll(evcResponse.mefServices().uni().evc());
            }
        } catch (NetconfException | InterruptedException e1) {
            log.warn("Unexpected error on applyFlowRules", e1);
        }

        for (FlowRule fr : rules) {

            // IP SA Filtering can only apply to Port 0 optics
            if (fr.selector().getCriterion(Type.IPV4_SRC) != null &&
                    fr.selector().getCriterion(Type.IN_PORT) != null &&
                    ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) {
                parseFrForSaRange(frAdded, saRangeList, fr);

            // EVCs will be defined by Flow Rules relating to VIDs
            } else if (fr.selector().getCriterion(Type.VLAN_VID) != null &&
                    fr.selector().getCriterion(Type.IN_PORT) != null) {
                //There could be many Flow Rules for one EVC depending on the ceVlanMap
                //Cannot build up the EVC until we know the details - the key is the tableID and port
                parseFrForEvcs(frAdded, evcMap, activeEvcs, portAssignment, fr);
            } else {
                log.info("Unexpected Flow Rule type applied: " + fr);
            }
        }

        //If there are IPv4 Flow Rules created commit them now through the
        //MseaSaFiltering service
        if (saRangeList.size() > 0) {
            try {
                mseaSaFilteringService.setMseaSaFiltering(
                            buildSaFilteringObject(saRangeList), session, DatastoreId.RUNNING);
            } catch (NetconfException e) {
                log.error("Error applying Flow Rules to SA Filtering - will try again: " + e.getMessage());
                sessionMutex.release();
                return frAdded;
            }
        }
        //If there are EVC flow rules then populate the MseaUniEvc part of EA1000
        if (evcMap.size() > 0) {
            List<Evc> evcList = evcMap.entrySet().stream()
                    .map(x -> x.getValue())
                    .collect(Collectors.toList());
            Uni uni = new DefaultUni();
            URI deviceName = handler().data().deviceId().uri();
            uni.name(new Identifier45("Uni-on-"
                    + deviceName.getSchemeSpecificPart()));
            uni.evc(evcList);

            List<BwpGroup> bwpGroupList = new ArrayList<BwpGroup>();
            BwpGroup bwpGrp = new DefaultBwpGroup();
            bwpGrp.groupIndex((short) 0);
            bwpGroupList.add(bwpGrp);
            Profiles profiles = new DefaultProfiles();
            profiles.bwpGroup(bwpGroupList);

            MefServices mefServices = new DefaultMefServices();
            mefServices.uni(uni);
            mefServices.profiles(profiles);

            MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
            mseaUniEvcServiceFilter.mefServices(mefServices);
            try {
                mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, DatastoreId.RUNNING);
            } catch (NetconfException e) {
                log.error("Error applying Flow Rules to EVC - will try again: " + e.getMessage());
                sessionMutex.release();
                return frAdded;
            }
        }
        sessionMutex.release();
        return frAdded;
    }

    /**
     * Remove flow rules from the EA1000.
     * Since the EA1000 does not have any 'real' flow entries these are converted 2 configuration
     * areas on the EA1000 NETCONF model - to SA filtering YANG model and to EVC UNI YANG model.
     *
     * @param rulesToRemove A collection of Flow Rules to be removed to the EA1000
     * @return A collection of the Flow Rules that have been removed.
     */
    @Override
    public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rulesToRemove) {
        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
        MseaSaFilteringNetconfService mseaSaFilteringService =
                (MseaSaFilteringNetconfService) checkNotNull(handler().get(MseaSaFilteringNetconfService.class));
        MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc =
                (MseaUniEvcServiceNetconfService) checkNotNull(handler().get(MseaUniEvcServiceNetconfService.class));
        UniSideInterfaceAssignmentEnum portAssignment = UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST;
        log.debug("removeFlowRules() called on EA1000FlowRuleProgrammable with {} rules.", rulesToRemove.size());

        if (rulesToRemove.size() == 0) {
            return rulesToRemove;
        }

        //Retrieve the list of actual EVCs and the CeVlanMaps from device
        List<Evc> activeEvcs = new ArrayList<>();
        List<Short> acvtiveFiltRanges = new ArrayList<>();
        try {
            sessionMutex.acquire();
            MseaUniEvcService evcResponse =
                    mseaUniEvcServiceSvc.getmseaUniEvcCeVlanMaps(session, DatastoreId.RUNNING);
            //There could be zero or more EVCs
            if (evcResponse != null && evcResponse.mefServices() != null && evcResponse.mefServices().uni() != null) {
                activeEvcs.addAll(evcResponse.mefServices().uni().evc());
            }
            mseaSaFilteringService.getConfigMseaSaFilterIds(session).forEach(
                    r -> acvtiveFiltRanges.add(r.rangeId()));

        } catch (NetconfException | InterruptedException e1) {
            log.warn("Error on removeFlowRules.", e1);
        }

        List<SourceAddressRange> saRangeList = new ArrayList<SourceAddressRange>();
        Map<Integer, String> ceVlanMapMap = new HashMap<>();
        Map<Integer, List<Short>> flowIdMap = new HashMap<>();

        Collection<FlowRule> rulesRemoved = new HashSet<FlowRule>();
        for (FlowRule ruleToRemove : rulesToRemove) {
            // IP SA Filtering can only apply to Port 0 optics
            if (ruleToRemove.selector().getCriterion(Type.IPV4_SRC) != null &&
                    ruleToRemove.selector().getCriterion(Type.IN_PORT) != null &&
                    ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port().toLong() == 0) {
                SourceAddressRange sar = new DefaultSourceAddressRange();
                sar.rangeId((short) ruleToRemove.tableId());
                acvtiveFiltRanges.remove(Short.valueOf((short) ruleToRemove.tableId()));
                rulesRemoved.add(ruleToRemove);
                saRangeList.add(sar);

            } else if (ruleToRemove.selector().getCriterion(Type.VLAN_VID) != null &&
                    ruleToRemove.selector().getCriterion(Type.IN_PORT) != null) {
                PortNumber portNumber = ((PortCriterion) ruleToRemove.selector().getCriterion(Type.IN_PORT)).port();
                VlanId vlanId = ((VlanIdCriterion) ruleToRemove.selector().getCriterion(Type.VLAN_VID)).vlanId();
                int evcId = ruleToRemove.tableId();
                int evcKey = (evcId << 2) + (int) portNumber.toLong();
                String activeCeVlanMap = "";
                //If this is one of many VLANs belonging to an EVC then we should only remove this VLAN
                // from the ceVlanMap and not the whole EVC
                if (!ceVlanMapMap.containsKey(evcKey)) {
                    for (Evc activeEvc:activeEvcs) {
                        if (activeEvc.evcIndex() == evcId) {
                            if (Ea1000Port.fromNum(portNumber.toLong()).nOrC(portAssignment) ==
                                    UniSide.CUSTOMER) {
                                activeCeVlanMap = activeEvc.evcPerUni().evcPerUnic().ceVlanMap().string();
                            } else if (Ea1000Port.fromNum(portNumber.toLong()).nOrC(portAssignment) ==
                                    UniSide.NETWORK) {
                                activeCeVlanMap = activeEvc.evcPerUni().evcPerUnin().ceVlanMap().string();
                            }
                        }
                    }
                }

                ceVlanMapMap.put(evcKey, CeVlanMapUtils.removeFromCeVlanMap(activeCeVlanMap, vlanId.id()));
                if (!flowIdMap.containsKey(evcKey)) {
                    flowIdMap.put(evcKey, new ArrayList<>());
                }
                flowIdMap.get(evcKey).add(vlanId.id());
                rulesRemoved.add(ruleToRemove);

            } else {
                log.info("Unexpected Flow Rule type removal: " + ruleToRemove);
            }
        }

        //If there are IPv4 Flow Rules created commit them now through the
        //MseaSaFiltering service
        if (saRangeList.size() > 0 && acvtiveFiltRanges.size() == 0) {
            try {
                SourceIpaddressFiltering saFilter =
                        new DefaultSourceIpaddressFiltering();
                MseaSaFilteringOpParam mseaSaFiltering = new MseaSaFilteringOpParam();
                mseaSaFiltering.sourceIpaddressFiltering(saFilter);

                mseaSaFilteringService.deleteMseaSaFilteringRange(
                        mseaSaFiltering, session, DatastoreId.RUNNING);
            } catch (NetconfException e) {
                log.warn("Remove FlowRule on MseaSaFilteringService could not delete all SARules - "
                        + "they may already have been deleted: " + e.getMessage());
            }
        } else if (saRangeList.size() > 0) {
            try {
                mseaSaFilteringService.deleteMseaSaFilteringRange(
                        buildSaFilteringObject(saRangeList), session, DatastoreId.RUNNING);
            } catch (NetconfException e) {
                log.warn("Remove FlowRule on MseaSaFilteringService could not delete SARule - "
                        + "it may already have been deleted: " + e.getMessage());
            }
        }

        if (ceVlanMapMap.size() > 0) {
            try {
                mseaUniEvcServiceSvc.removeEvcUniFlowEntries(ceVlanMapMap, flowIdMap,
                        session, DatastoreId.RUNNING, portAssignment);
            } catch (NetconfException e) {
                log.warn("Remove FlowRule on MseaUniEvcService could not delete EVC - "
                        + "it may already have been deleted: " + e.getMessage());
            }
        }

        sessionMutex.release();
        return rulesRemoved;
    }

    /**
     * An internal method for extracting one EVC from a list and returning its ceVlanMap.
     *
     * @param evcList - the list of known EVCs
     * @param evcIndex - the index of the EVC we're looking for
     * @param side - the side of the UNI
     * @return - the CEVlanMap we're looking for
     */
    private String getCeVlanMapForIdxFromEvcList(List<Evc> evcList, long evcIndex, UniSide side) {
        if (evcList != null && evcList.size() > 0) {
            for (Evc evc:evcList) {
                if (evc.evcIndex() == evcIndex && evc.evcPerUni() != null) {
                    if (side == UniSide.CUSTOMER &&
                        evc.evcPerUni().evcPerUnic() != null &&
                        evc.evcPerUni().evcPerUnic().ceVlanMap() != null) {
                        return evc.evcPerUni().evcPerUnic().ceVlanMap().string();
                    } else if (side == UniSide.NETWORK &&
                        evc.evcPerUni().evcPerUnin() != null &&
                        evc.evcPerUni().evcPerUnin().ceVlanMap() != null) {
                        return evc.evcPerUni().evcPerUnin().ceVlanMap().string();
                    }
                }
            }
        }

        return ""; //The EVC required was not in the list
    }

    /**
     * An internal method to convert from a FlowRule to SARange.
     *
     * @param frList A collection of flow rules
     * @param saRangeList A list of SARanges
     * @param fr A flow rule
     */
    private void parseFrForSaRange(Collection<FlowRule> frList, List<SourceAddressRange> saRangeList, FlowRule fr) {
        String ipAddrStr = fr.selector().getCriterion(Type.IPV4_SRC).toString().substring(9);
        log.debug("Applying IP address to " + ipAddrStr
                + " (on Port 0) to IP SA Filtering on EA1000 through NETCONF");

        SourceAddressRange sar =
                new DefaultSourceAddressRange();

        sar.rangeId((short) fr.tableId());
        sar.name("Flow:" + fr.id().toString());
        sar.ipv4AddressPrefix(ipAddrStr);

        frList.add(fr);
        saRangeList.add(sar);
    }

    private void parseFrForEvcs(Collection<FlowRule> frList, Map<Integer, Evc> evcMap,
            List<Evc> activeEvcs, UniSideInterfaceAssignmentEnum portAssignment, FlowRule fr) {
        //There could be many Flow Rules for one EVC depending on the ceVlanMap
        //Cannot build up the EVC until we know the details - the key is the tableID and port
        Ea1000Port port = Ea1000Port.fromNum(
                ((PortCriterion) fr.selector().getCriterion(Type.IN_PORT)).port().toLong());
        Integer evcKey = (fr.tableId() << 2) + port.portNum();
        VlanId sourceVid = ((VlanIdCriterion) fr.selector().getCriterion(Type.VLAN_VID)).vlanId();
        FlowMapping fm = new DefaultFlowMapping();
        fm.ceVlanId(VlanIdType.of(sourceVid.id()));
        fm.flowId(BigInteger.valueOf(fr.id().value()));

        if (evcMap.containsKey(evcKey)) { //Is there an entry already for this EVC and port?
            //Replace ceVlanMap
            if (port.nOrC(portAssignment) == UniSide.CUSTOMER) {
                evcMap.get(evcKey).evcPerUni().evcPerUnic().addToFlowMapping(fm);
                ServiceListType newCeVlanMap = new ServiceListType(
                        CeVlanMapUtils.addtoCeVlanMap(
                                evcMap.get(evcKey).evcPerUni().evcPerUnic().ceVlanMap().toString(),
                                sourceVid.toShort()));
                evcMap.get(evcKey).evcPerUni().evcPerUnic().ceVlanMap(newCeVlanMap);
            } else {
                evcMap.get(evcKey).evcPerUni().evcPerUnin().addToFlowMapping(fm);
                ServiceListType newCeVlanMap = new ServiceListType(
                        CeVlanMapUtils.addtoCeVlanMap(
                                evcMap.get(evcKey).evcPerUni().evcPerUnin().ceVlanMap().toString(),
                                sourceVid.toShort()));
                evcMap.get(evcKey).evcPerUni().evcPerUnin().ceVlanMap(newCeVlanMap);
            }
        } else if (evcMap.containsKey((evcKey ^ 1))) { //Is there an entry for this EVC but the opposite port?
            TagManipulation tm = getTagManipulation(fr);
            if (port.nOrC(portAssignment) == UniSide.NETWORK) {
                ServiceListType newCeVlanMap = new ServiceListType(
                        CeVlanMapUtils.addtoCeVlanMap(
                                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ceVlanMap().toString(),
                                sourceVid.toShort()));
                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ceVlanMap(newCeVlanMap);
                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().tagManipulation(tm);
                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().addToFlowMapping(fm);
                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnin().ingressBwpGroupIndex(getMeterId(fr.treatment()));
            } else {
                ServiceListType newCeVlanMap = new ServiceListType(
                        CeVlanMapUtils.addtoCeVlanMap(
                                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ceVlanMap().toString(),
                                sourceVid.toShort()));
                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ceVlanMap(newCeVlanMap);
                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().tagManipulation(tm);
                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().addToFlowMapping(fm);
                evcMap.get(evcKey ^ 1).evcPerUni().evcPerUnic().ingressBwpGroupIndex(getMeterId(fr.treatment()));
            }
        } else {
            Evc evc = new DefaultEvc();
            EvcPerUnin epun = new CustomEvcPerUnin();
            EvcPerUnic epuc = new CustomEvcPerUnic();
            TagManipulation tm = getTagManipulation(fr);

            UniSide side = port.nOrC(portAssignment);
            String oldCeVlanMap = getCeVlanMapForIdxFromEvcList(activeEvcs, fr.tableId(), side);
            String newCeVlanMap =
                    CeVlanMapUtils.addtoCeVlanMap(oldCeVlanMap, sourceVid.id());
            String oppositeCeVlanMap =
                    getCeVlanMapForIdxFromEvcList(activeEvcs, fr.tableId(),
                            port.opposite().nOrC(portAssignment));
            oppositeCeVlanMap = oppositeCeVlanMap.isEmpty() ? "0" : oppositeCeVlanMap;
            if (side == UniSide.NETWORK) {
                epun.ceVlanMap(new ServiceListType(newCeVlanMap));
                epun.tagManipulation(tm);
                epun.addToFlowMapping(fm);
                epun.ingressBwpGroupIndex(getMeterId(fr.treatment()));

                epuc.ceVlanMap(new ServiceListType(oppositeCeVlanMap));
                epuc.ingressBwpGroupIndex(new Long(0));
            } else {
                epuc.ceVlanMap(new ServiceListType(newCeVlanMap));
                epuc.tagManipulation(tm);
                epuc.addToFlowMapping(fm);
                epuc.ingressBwpGroupIndex(getMeterId(fr.treatment()));

                epun.ceVlanMap(new ServiceListType(oppositeCeVlanMap));
                epun.ingressBwpGroupIndex(new Long(0));
            }

            evc.evcIndex(fr.tableId());
            evc.name(new Identifier45("EVC-" + String.valueOf(fr.tableId())));

            DefaultEvcPerUni epu = new DefaultEvcPerUni();
            epu.evcPerUnin(epun);
            epu.evcPerUnic(epuc);
            evc.evcPerUni(epu);

            evcMap.put(evcKey, evc);
        }

        frList.add(fr);
    }


    private MseaSaFilteringOpParam buildSaFilteringObject(List<SourceAddressRange> saRangeList) {
        InterfaceEth0 saIf = new DefaultInterfaceEth0();
        for (SourceAddressRange sa:saRangeList) {
            saIf.addToSourceAddressRange(sa);
        }
        saIf.filterAdminState(FilterAdminStateEnum.BLACKLIST);

        SourceIpaddressFiltering saFilter =
                new DefaultSourceIpaddressFiltering();
        saFilter.interfaceEth0(saIf);

        MseaSaFilteringOpParam mseaSaFiltering = new MseaSaFilteringOpParam();
        mseaSaFiltering.sourceIpaddressFiltering(saFilter);

        return mseaSaFiltering;
    }

    private Collection<FlowEntry> convertSaFilteringToFlowRules(
            MseaSaFiltering saFilteringCurrent, ApplicationId appId) {
        Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();

        List<SourceAddressRange> saRangelist =
                saFilteringCurrent.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
        Criterion matchInPort = Criteria.matchInPort(PortNumber.portNumber(0));
        TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();

        if (saRangelist != null) {
            for (SourceAddressRange sa : saRangelist) {
                Criterion matchIpSrc = Criteria.matchIPSrc(IpPrefix.valueOf(sa.ipv4AddressPrefix()));

                TrafficSelector selector = tsBuilder.add(matchIpSrc).add(matchInPort).build();

                TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder();
                TrafficTreatment treatment = trBuilder.drop().build();

                FlowRule.Builder feBuilder = new DefaultFlowRule.Builder();
                if (sa.name() != null && sa.name().startsWith("Flow:")) {
                    String[] nameParts = sa.name().split(":");
                    Long cookie = Long.valueOf(nameParts[1], 16);
                    feBuilder = feBuilder.withCookie(cookie);
                } else {
                    feBuilder = feBuilder.fromApp(appId);
                }

                FlowRule fr = feBuilder
                        .forDevice(handler().data().deviceId())
                        .withSelector(selector)
                        .withTreatment(treatment)
                        .forTable(sa.rangeId())
                        .makePermanent()
                        .withPriority(PRIORITY_DEFAULT)
                        .build();

                flowEntryCollection.add(
                        new DefaultFlowEntry(fr, FlowEntryState.ADDED, 0, 0, 0));
            }
        }
        return flowEntryCollection;
    }


    private Collection<FlowEntry> convertEvcUniToFlowRules(
            MseaUniEvcService uniEvcCurrent, UniSideInterfaceAssignmentEnum portAssignment) {
        Collection<FlowEntry> flowEntryCollection = new HashSet<FlowEntry>();

        if (uniEvcCurrent == null || uniEvcCurrent.mefServices() == null ||
                uniEvcCurrent.mefServices().uni() == null || uniEvcCurrent.mefServices().uni().evc() == null) {
            log.info("No EVC's found when getting flow rules");
            return flowEntryCollection;
        }

        for (Evc evc:uniEvcCurrent.mefServices().uni().evc()) {
            FlowRule.Builder frBuilder = new DefaultFlowRule.Builder();
            TrafficSelector.Builder tsBuilder = DefaultTrafficSelector.builder();

            TrafficTreatment uniNTreatment = treatmentForUniSde(evc.evcPerUni(), true);
            //Depending on the ceVlanMap there may be multiple VLans and hence multiple flow entries
            Short[] vlanIdsUniN =
                    CeVlanMapUtils.getVlanSet(ceVlanMapForUniSide(evc.evcPerUni(), true));
            for (Short vlanId:vlanIdsUniN) {
                if (vlanId == 0) {
                    continue;
                }
                Criterion uniNportCriterion = criterionPortForUniSide(portAssignment, true);
                TrafficSelector tsUniN = tsBuilder.matchVlanId(VlanId.vlanId(vlanId)).add(uniNportCriterion).build();
                long flowId = getFlowIdForVlan(evc.evcPerUni().evcPerUnin().flowMapping(), vlanId);

                FlowRule frUniN = frBuilder
                    .forDevice(handler().data().deviceId())
                    .withSelector(tsUniN)
                    .withTreatment(uniNTreatment)
                    .forTable(new Long(evc.evcIndex()).intValue()) //narrowing to int
                    .makePermanent()
                    .withPriority(PRIORITY_DEFAULT)
                    .withCookie(flowId)
                    .build();
                flowEntryCollection.add(new DefaultFlowEntry(frUniN, FlowEntryState.ADDED, 0, 0, 0));
            }

            TrafficTreatment uniCTreatment = treatmentForUniSde(evc.evcPerUni(), false);
            //Depending on the ceVlanMap there may be multiple VLans and hence multiple flow entries
            Short[] vlanIdsUniC =
                    CeVlanMapUtils.getVlanSet(ceVlanMapForUniSide(evc.evcPerUni(), false));
            if (vlanIdsUniC != null && vlanIdsUniC.length > 0) {
                for (Short vlanId:vlanIdsUniC) {
                    if (vlanId == 0) {
                        continue;
                    }
                    Criterion uniCportCriterion = criterionPortForUniSide(portAssignment, false);
                    TrafficSelector tsUniC =
                            tsBuilder.matchVlanId(VlanId.vlanId(vlanId)).add(uniCportCriterion).build();
                    long flowId = getFlowIdForVlan(evc.evcPerUni().evcPerUnic().flowMapping(), vlanId);

                    FlowRule frUniC = frBuilder
                            .forDevice(handler().data().deviceId())
                            .withSelector(tsUniC)
                            .withTreatment(uniCTreatment)
                            .forTable(new Long(evc.evcIndex()).intValue()) //narrowing to int
                            .makePermanent()
                            .withPriority(PRIORITY_DEFAULT)
                            .withCookie(flowId)
                            .build();
                    flowEntryCollection.add(new DefaultFlowEntry(frUniC, FlowEntryState.ADDED, 0, 0, 0));
                }
            }
        }

        return flowEntryCollection;
    }

    private long getFlowIdForVlan(List<FlowMapping> fmList, Short vlanId) {
        if (fmList == null || vlanId == null) {
            log.warn("Flow Mapping list is null when reading EVCs");
            return -1L;
        }
        for (FlowMapping fm:fmList) {
            if (fm.ceVlanId().uint16() == vlanId.intValue()) {
                return fm.flowId().longValue();
            }
        }
        return 0L;
    }

    private String ceVlanMapForUniSide(
            EvcPerUni evcPerUni, boolean portN) {
        if (portN) {
            return evcPerUni.evcPerUnin().ceVlanMap().string();
        } else {
            return evcPerUni.evcPerUnic().ceVlanMap().string();
        }
    }

    private Criterion criterionPortForUniSide(
            UniSideInterfaceAssignmentEnum portAssignment, boolean portN) {
        boolean cOnOptics = (portAssignment == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS);
        int portNum = ((cOnOptics && portN) || (!cOnOptics && !portN)) ? 1 : 0;
        return Criteria.matchInPort(PortNumber.portNumber(portNum));
    }

    private TrafficTreatment treatmentForUniSde(
            EvcPerUni evcPerUni, boolean portN) {
        TrafficTreatment.Builder trBuilder = DefaultTrafficTreatment.builder();

        TagManipulation tm = null;
        short meterId = 0;
        if (portN) {
            tm = evcPerUni.evcPerUnin().tagManipulation();
            meterId = (short) evcPerUni.evcPerUnin().ingressBwpGroupIndex();
        } else {
            tm = evcPerUni.evcPerUnic().tagManipulation();
            meterId = (short) evcPerUni.evcPerUnic().ingressBwpGroupIndex();
        }

        if (meterId > 0L) {
            trBuilder = trBuilder.meter(MeterId.meterId((long) meterId));
//            trBuilder = trBuilder.meter(MeterId.meterId(meterId)).transition(0);
        }

        if (tm == null) {
            return trBuilder.build(); //no tag manipulation found
        }

        if (tm.getClass().equals(DefaultTagPush.class)) {
            VlanId pushVlanNum = VlanId.vlanId((short) ((TagPush) tm).tagPush().outerTagVlan().uint16());
            PushTagTypeEnum pushTagType = ((TagPush) tm).tagPush().pushTagType();
            //Note - the order of elements below MUST match the order of the Treatment in the stored FlowRule
            // to be an exactMatch. See DefaultFlowRule.exactMatch()
            trBuilder = trBuilder
                    .pushVlan(pushTagType.equals(PushTagTypeEnum.PUSHCTAG) ?
                            EtherType.VLAN.ethType() : EtherType.QINQ.ethType())
                    .setVlanId(pushVlanNum).transition(Integer.valueOf(0));

        } else if (tm.getClass().equals(DefaultTagPop.class)) {
            trBuilder = trBuilder.popVlan();

        } else if (tm.getClass().equals(DefaultTagOverwrite.class)) {
            TagOverwrite to = (TagOverwrite) tm;
            VlanId ovrVlanNum = VlanId
                    .vlanId((short) (
                            //There are 2 classes TagOverwrite - the other one is already imported
                            to
                            .tagOverwrite()
                            .outerTagVlan()
                            .uint16()));
            trBuilder = trBuilder.setVlanId(ovrVlanNum);

        }

        return trBuilder.build();
    }

    private static TagManipulation getTagManipulation(FlowRule fr) {
        boolean isPop = false;
        boolean isPush = false;
        VlanId vlanId = null;
        EthType ethType = EtherType.VLAN.ethType(); //Default
        for (Instruction inst:fr.treatment().allInstructions()) {
            if (inst.type() == Instruction.Type.L2MODIFICATION) {
                L2ModificationInstruction l2Mod = (L2ModificationInstruction) inst;
                if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_POP) {
                    isPop = true;
                } else if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_PUSH) {
                    isPush = true;
                    ethType = ((ModVlanHeaderInstruction) l2Mod).ethernetType();
                } else if (l2Mod.subtype() == L2ModificationInstruction.L2SubType.VLAN_ID) {
                    vlanId = ((ModVlanIdInstruction) l2Mod).vlanId();
                }
            }
        }

        if (isPop) {
            //The should be no vlanId in this case
            TagPop pop = new DefaultTagPop();
            org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
                .evcperuniextensionattributes.tagmanipulation
                .tagpop.TagPop popInner =
                    new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
                        .mseaunievcservice.evcperuniextensionattributes
                        .tagmanipulation.tagpop.DefaultTagPop();
            pop.tagPop(popInner);
            return pop;

        } else if (isPush && vlanId != null) {
            TagPush push = new DefaultTagPush();
            org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
                .evcperuniextensionattributes.tagmanipulation
                .tagpush.TagPush pushInner =
                    new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
                        .mseaunievcservice.evcperuniextensionattributes
                        .tagmanipulation.tagpush.DefaultTagPush();
            pushInner.outerTagVlan(new VlanIdType(vlanId.id()));
            pushInner.pushTagType(ethType.equals(EtherType.VLAN.ethType()) ?
                                PushTagTypeEnum.PUSHCTAG : PushTagTypeEnum.PUSHSTAG);
            push.tagPush(pushInner);
            return push;

        } else if (vlanId != null) { //This is overwrite, as it has vlanId, but not push or pop
            TagOverwrite ovr = new DefaultTagOverwrite();
            org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice
                .evcperuniextensionattributes.tagmanipulation
                .tagoverwrite.TagOverwrite ovrInner =
                    new org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317
                        .mseaunievcservice.evcperuniextensionattributes
                        .tagmanipulation.tagoverwrite.DefaultTagOverwrite();
            ovrInner.outerTagVlan(new VlanIdType(vlanId.id()));
            ovr.tagOverwrite(ovrInner);
            return ovr;
        }

        return null;
    }

    private static long getMeterId(TrafficTreatment treatment) {
        return (treatment.metered() != null && treatment.metered().meterId() != null)
                ? treatment.metered().meterId().id() : 0L;
    }

    /**
     * An enumerated type that characterises the 2 port layout of the EA1000 device.
     * The device is in an SFP package and has only 2 ports, the HOST port which
     * plugs in to the chassis (Port 1) and the Optics Port on the rear (Port 0).
     */
    public enum Ea1000Port {
        HOST(1),
        OPTICS(0);

        private int num = 0;
        private Ea1000Port(int num) {
            this.num = num;
        }

        /**
         * The numerical assignment of this port.
         * @return The port number
         */
        public int portNum() {
            return num;
        }

        /**
         * Return the enumerated value from a port number.
         * @param num The port number
         * @return An enumerated value
         */
        public static Ea1000Port fromNum(long num) {
            for (Ea1000Port a:Ea1000Port.values()) {
                if (a.num == num) {
                    return a;
                }
            }
            return HOST;
        }

        /**
         * Get the port that the UNI-N is present on.
         * @param side The assignment of UNI-side to port
         * @return An enumerated value
         */
        public static Ea1000Port uniNNum(UniSideInterfaceAssignmentEnum side) {
            if (side.equals(UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST)) {
                return OPTICS;
            } else {
                return HOST;
            }
        }

        /**
         * Get the port that the UNI-C is present on.
         * @param side The assignment of UNI-side to port
         * @return An enumerated value
         */
        public static Ea1000Port uniCNum(UniSideInterfaceAssignmentEnum side) {
            if (side.equals(UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST)) {
                return HOST;
            } else {
                return OPTICS;
            }
        }

        /**
         * Get the port opposite the current port.
         * @return An enumerated value for the opposite side
         */
        public Ea1000Port opposite() {
            if (this.equals(HOST)) {
                return OPTICS;
            } else {
                return HOST;
            }
        }

        /**
         * Evaluate which side of the UNI on the EA1000 device this port refers to.
         * @param side The assignment of UNI-side to port
         * @return An enumerated value representing the UniSide
         */
        public UniSide nOrC(UniSideInterfaceAssignmentEnum side) {
            if ((this == HOST && side == UniSideInterfaceAssignmentEnum.UNI_C_ON_HOST) ||
                    (this == OPTICS && side == UniSideInterfaceAssignmentEnum.UNI_C_ON_OPTICS)) {
                return UniSide.CUSTOMER;
            } else {
                return UniSide.NETWORK;
            }
        }
    }
}
