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

 * This work was partially supported by EC H2020 project METRO-HAUL (761727).
 */

package org.onosproject.drivers.odtn.openconfig;

import com.google.common.collect.ImmutableList;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.onlab.util.Frequency;
import org.onlab.util.Spectrum;
import org.onosproject.drivers.odtn.impl.DeviceConnectionCache;
import org.onosproject.drivers.odtn.impl.FlowRuleParser;
import org.onosproject.drivers.utilities.XmlConfigParser;
import org.onosproject.net.PortNumber;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.netconf.DatastoreId;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;
import org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Implementation of FlowRuleProgrammable interface for
 * OpenConfig terminal devices.
 */
public class ClientLineTerminalDeviceFlowRuleProgrammable
        extends AbstractHandlerBehaviour implements FlowRuleProgrammable {

    private static final Logger log =
            LoggerFactory.getLogger(ClientLineTerminalDeviceFlowRuleProgrammable.class);

    private static final String RPC_TAG_NETCONF_BASE =
            "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";

    private static final String RPC_CLOSE_TAG = "</rpc>";

    private static final String PREFIX_PORT = "port-";
    private static final String PREFIX_CHANNEL = "channel-";
    private static final String DEFAULT_OPERATIONAL_MODE = "0";
    private static final String DEFAULT_TARGET_POWER = "0";
    private static final String DEFAULT_ASSIGNMENT_INDEX = "1";
    private static final String DEFAULT_ALLOCATION_INDEX = "10";
    private static final int DEFAULT_RULE_PRIORITY = 10;
    private static final long DEFAULT_RULE_COOKIE = 1234L;
    private static final String OPERATION_DISABLE = "DISABLED";
    private static final String OPERATION_ENABLE = "ENABLED";
    private static final String OC_TYPE_PROT_OTN = "oc-opt-types:PROT_OTN";
    private static final String OC_TYPE_PROT_ETH = "oc-opt-types:PROT_ETHERNET";


    /**
     * Apply the flow entries specified in the collection rules.
     *
     * @param rules A collection of Flow Rules to be applied
     * @return The collection of added Flow Entries
     */
    @Override
    public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
        NetconfSession session = getNetconfSession();
        if (session == null) {
            openConfigError("null session");
            return ImmutableList.of();
        }

        // Apply the  rules on the device
        Collection<FlowRule> added = rules.stream()
                .map(r -> new TerminalDeviceFlowRule(r, getLinePorts()))
                .filter(xc -> applyFlowRule(session, xc))
                .collect(Collectors.toList());

        for (FlowRule flowRule : added) {
            log.info("OpenConfig added flowrule {}", flowRule);
            getConnectionCache().add(did(), ((TerminalDeviceFlowRule) flowRule).connectionName(), flowRule);
        }

        //Print out number of rules sent to the device (without receiving errors)
        openConfigLog("applyFlowRules added {}", added.size());

        return added;
    }

    /**
     * Get the flow entries that are present on the device.
     *
     * @return A collection of Flow Entries
     */
    @Override
    public Collection<FlowEntry> getFlowEntries() {
        Collection<FlowEntry> fetched = fetchConnectionsFromDevice().stream()
                .map(fr -> new DefaultFlowEntry(fr, FlowEntry.FlowEntryState.ADDED, 0, 0, 0))
                .collect(Collectors.toList());

        //Print out number of rules actually found on the device that are also included in the cache
        openConfigLog("getFlowEntries fetched connections {}", fetched.size());

        return fetched;
    }

    /**
     * Remove the specified flow rules.
     *
     * @param rules A collection of Flow Rules to be removed
     * @return The collection of removed Flow Entries
     */
    @Override
    public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
        NetconfSession session = getNetconfSession();
        if (session == null) {
            openConfigError("null session");
            return ImmutableList.of();
        }
        List<FlowRule> removed = new ArrayList<>();
        for (FlowRule r : rules) {
            try {
                TerminalDeviceFlowRule termFlowRule = new TerminalDeviceFlowRule(r, getLinePorts());
                removeFlowRule(session, termFlowRule);
                getConnectionCache().remove(did(), r);
                removed.add(r);
            } catch (Exception e) {
                openConfigError("Error {}", e);
                continue;
            }
        }

        //Print out number of removed rules from the device (without receiving errors)
        openConfigLog("removeFlowRules removed {}", removed.size());

        return removed;
    }

    private DeviceConnectionCache getConnectionCache() {
        return DeviceConnectionCache.init();
    }

    // Context so XPath expressions are aware of XML namespaces
    private static final NamespaceContext NS_CONTEXT = new NamespaceContext() {
        @Override
        public String getNamespaceURI(String prefix) {
            if (prefix.equals("oc-platform-types")) {
                return "http://openconfig.net/yang/platform-types";
            }
            if (prefix.equals("oc-opt-term")) {
                return "http://openconfig.net/yang/terminal-device";
            }
            return null;
        }

        @Override
        public Iterator getPrefixes(String val) {
            return null;
        }

        @Override
        public String getPrefix(String uri) {
            return null;
        }
    };


    /**
     * Helper method to get the device id.
     */
    private DeviceId did() {
        return data().deviceId();
    }

    /**
     * Helper method to log from this class adding DeviceId.
     */
    private void openConfigLog(String format, Object... arguments) {
        log.info("OPENCONFIG {}: " + format, did(), arguments);
    }

    /**
     * Helper method to log an error from this class adding DeviceId.
     */
    private void openConfigError(String format, Object... arguments) {
        log.error("OPENCONFIG {}: " + format, did(), arguments);
    }


    /**
     * Helper method to get the Netconf Session.
     */
    private NetconfSession getNetconfSession() {
        NetconfController controller =
                checkNotNull(handler().get(NetconfController.class));
        return controller.getNetconfDevice(did()).getSession();
    }


    /**
     * Construct a String with a Netconf filtered get RPC Message.
     *
     * @param filter A valid XML tree with the filter to apply in the get
     * @return a String containing the RPC XML Document
     */
    private String filteredGetBuilder(String filter) {
        StringBuilder rpc = new StringBuilder(RPC_TAG_NETCONF_BASE);
        rpc.append("<get>");
        rpc.append("<filter type='subtree'>");
        rpc.append(filter);
        rpc.append("</filter>");
        rpc.append("</get>");
        rpc.append(RPC_CLOSE_TAG);
        return rpc.toString();
    }

    /**
     * Construct a get request to retrieve Components and their
     * properties (for the ONOS port, index).
     *
     * @return The filt content to send to the device.
     */
    private String getComponents() {
        StringBuilder filt = new StringBuilder();
        filt.append("<components xmlns='http://openconfig.net/yang/platform'>");
        filt.append(" <component>");
        filt.append("  <name/>");
        filt.append("  <properties/>");
        filt.append(" </component>");
        filt.append("</components>");
        return filteredGetBuilder(filt.toString());
    }

    /**
     * Construct a get request to retrieve Optical Channels and
     * the line port they are using.
     * <p>
     * This method is used to query the device so we can find the
     * OpticalChannel component name that used a given line port.
     *
     * @return The filt content to send to the device.
     */
    private String getOpticalChannels() {
        StringBuilder filt = new StringBuilder();
        filt.append("<components xmlns='http://openconfig.net/yang/platform'>");
        filt.append(" <component>");
        filt.append("  <name/>");
        filt.append("  <state/>");
        filt.append("  <oc-opt-term:optical-channel xmlns:oc-opt-term"
                + " = 'http://openconfig.net/yang/terminal-device'>");
        filt.append("    <oc-opt-term:config>");
        filt.append("     <oc-opt-term:line-port/>");
        filt.append("    </oc-opt-term:config>");
        filt.append("  </oc-opt-term:optical-channel>");
        filt.append(" </component>");
        filt.append("</components>");
        return filteredGetBuilder(filt.toString());
    }

    /**
     * Get the OpenConfig component name for the OpticalChannel component
     * associated to the passed port number (typically a line side port, already
     * mapped to ONOS port).
     *
     * @param session    The netconf session to the device.
     * @param portNumber ONOS port number of the Line port ().
     * @return the channel component name or null
     */
    private String getOpticalChannel(NetconfSession session,
                                     PortNumber portNumber) {
        try {
            checkNotNull(session);
            checkNotNull(portNumber);
            XPath xp = XPathFactory.newInstance().newXPath();
            xp.setNamespaceContext(NS_CONTEXT);

            // Get the port name for a given port number
            // We could iterate the port annotations too, no need to
            // interact with device.
            String xpGetPortName =
                    "/rpc-reply/data/components/"
                            +
                            "component[./properties/property[name='onos-index']/config/value ='" +
                            portNumber.toLong() + "']/"
                            + "name/text()";

            // Get all the components and their properties
            String compReply = session.rpc(getComponents()).get();
            DocumentBuilderFactory builderFactory =
                    DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
            Document document =
                    builder.parse(new InputSource(new StringReader(compReply)));
            String portName = xp.evaluate(xpGetPortName, document);
            String xpGetOptChannelName =
                    "/rpc-reply/data/components/"
                            + "component[./optical-channel/config/line-port='" + portName +
                            "']/name/text()";

            String optChannelReply = session.rpc(getOpticalChannels()).get();
            document =
                    builder.parse(new InputSource(new StringReader(optChannelReply)));
            return xp.evaluate(xpGetOptChannelName, document);
        } catch (Exception e) {
            openConfigError("Exception {}", e);
            return null;
        }
    }

    private void setLogicalChannel(NetconfSession session, String operation, String logChannel)
            throws NetconfException {
        StringBuilder sb = new StringBuilder();

        sb.append("<terminal-device xmlns='http://openconfig.net/yang/terminal-device'>");
        sb.append("<logical-channels>");
        sb.append("<channel>");
        sb.append("<index>" + logChannel + "</index>");
        sb.append("<config>");
        sb.append("<admin-state>" + operation + "</admin-state>");
        sb.append("</config>");
        sb.append("</channel>");
        sb.append("</logical-channels>");
        sb.append("</terminal-device>");

        boolean ok =
                session.editConfig(DatastoreId.RUNNING, null, sb.toString());
        if (!ok) {
            throw new NetconfException("error writing the logical channel");
        }
    }

    private void setOpticalChannelFrequency(NetconfSession session, String optChannel, Frequency freq)
            throws NetconfException {
        StringBuilder sb = new StringBuilder();

        sb.append("<components xmlns='http://openconfig.net/yang/platform'>");
        sb.append("<component>");
        sb.append("<name>" + PREFIX_CHANNEL + optChannel + "</name>");
        sb.append("<oc-opt-term:optical-channel xmlns:oc-opt-term='http://openconfig.net/yang/terminal-device'>");
        sb.append("<oc-opt-term:config>");
        sb.append("<oc-opt-term:frequency>" + (long) freq.asMHz() + "</oc-opt-term:frequency>");
        sb.append("<oc-opt-term:target-output-power>" + DEFAULT_TARGET_POWER + "</oc-opt-term:target-output-power>");
        sb.append("<oc-opt-term:operational-mode>" + DEFAULT_OPERATIONAL_MODE + "</oc-opt-term:operational-mode>");
        sb.append("<oc-opt-term:line-port>" + PREFIX_PORT + optChannel + "</oc-opt-term:line-port>");
        sb.append("</oc-opt-term:config>");
        sb.append("</oc-opt-term:optical-channel>");
        sb.append("</component>");
        sb.append("</components>");

        boolean ok =
                session.editConfig(DatastoreId.RUNNING, null, sb.toString());
        if (!ok) {
            throw new NetconfException("error writing channel frequency");
        }
    }

    private void setLogicalChannelAssignment(NetconfSession session, String operation, String client, String line,
                                             String assignmentIndex, String allocationIndex)
            throws NetconfException {
        StringBuilder sb = new StringBuilder();

        sb.append("<terminal-device xmlns='http://openconfig.net/yang/terminal-device'>");
        sb.append("<logical-channels>");
        sb.append("<channel>");
        sb.append("<index>" + client + "</index>");
        sb.append("<config>");
        sb.append("<admin-state>" + operation + "</admin-state>");
        sb.append("</config>");
        sb.append("<logical-channel-assignments>");
        sb.append("<assignment>");
        sb.append("<index>" + assignmentIndex + "</index>");
        sb.append("<config>");
        sb.append("<logical-channel>" + line + "</logical-channel>");
        sb.append("<allocation>" + allocationIndex + "</allocation>");
        sb.append("</config>");
        sb.append("</assignment>");
        sb.append("</logical-channel-assignments>");
        sb.append("</channel>");
        sb.append("</logical-channels>");
        sb.append("</terminal-device>");

        boolean ok =
                session.editConfig(DatastoreId.RUNNING, null, sb.toString());
        if (!ok) {
            throw new NetconfException("error writing logical channel assignment");
        }
    }

    /**
     * Apply a single flowrule to the device.
     *
     * --- Directionality details:
     * Driver supports ADD (INGRESS) and DROP (EGRESS) rules generated by OpticalCircuit/OpticalConnectivity intents
     * the format of the rules are checked in class TerminalDeviceFlowRule
     *
     * However, the physical transponder is always bidirectional as specified in OpenConfig YANG models
     * therefore ADD and DROP rules are mapped in the same xml that ENABLE (and tune) a transponder port.
     *
     * If the intent is generated as bidirectional both ADD and DROP flowrules are generated for each device, thus
     * the same xml is sent twice to the device.
     *
     * @param session   The Netconf session.
     * @param rule      Flow Rules to be applied.
     * @return true if no Netconf errors are received from the device when xml is sent
     * @throws NetconfException if exchange goes wrong
     */
    protected boolean applyFlowRule(NetconfSession session, TerminalDeviceFlowRule rule) {

        //Configuration of LINE side, used for OpticalConnectivity intents
        //--- configure central frequency
        //--- enable the line port
        if (rule.type == TerminalDeviceFlowRule.Type.LINE_INGRESS ||
                rule.type == TerminalDeviceFlowRule.Type.LINE_EGRESS) {

            FlowRuleParser frp = new FlowRuleParser(rule);
            String componentName = frp.getPortNumber().toString();
            Frequency centralFrequency = frp.getCentralFrequency();

            StringBuilder componentConf = new StringBuilder();

            log.info("Sending LINE FlowRule to device {} LINE port {}, frequency {}",
                    did(), componentName, centralFrequency);

            try {
                setOpticalChannelFrequency(session, componentName, centralFrequency);
            } catch (NetconfException e) {
                log.error("Error writing central frequency in the component");
                return false;
            }

            try {
                setLogicalChannel(session, OPERATION_ENABLE, componentName);
            } catch (NetconfException e) {
                log.error("Error enabling the logical channel");
                return false;
            }
        }

        //Configuration of CLIENT side, used for OpticalCircuit intents
        //--- associate the client port to the line port
        //--- enable the client port
        //
        //Assumes only one "assignment" per logical-channel with index 1
        //TODO check the OTN mapping of client ports into the line port frame specified by parameter "<allocation>"
        if (rule.type == TerminalDeviceFlowRule.Type.CLIENT_INGRESS ||
                rule.type == TerminalDeviceFlowRule.Type.CLIENT_EGRESS) {

            String clientPortName;
            String linePortName;
            if (rule.type == TerminalDeviceFlowRule.Type.CLIENT_INGRESS) {
                clientPortName = rule.inPort().toString();
                linePortName = rule.outPort().toString();
            } else {
                clientPortName = rule.outPort().toString();
                linePortName = rule.inPort().toString();
            }

            log.info("Sending CLIENT FlowRule to device {} CLIENT port: {}, LINE port {}",
                    did(), clientPortName, linePortName);

            try {
                setLogicalChannelAssignment(session, OPERATION_ENABLE, clientPortName, linePortName,
                        DEFAULT_ASSIGNMENT_INDEX, DEFAULT_ALLOCATION_INDEX);
            } catch (NetconfException e) {
                log.error("Error setting the logical channel assignment");
                return false;
            }
        }

        return true;
    }

    protected boolean removeFlowRule(NetconfSession session, TerminalDeviceFlowRule rule)
            throws NetconfException {

        //Configuration of LINE side, used for OpticalConnectivity intents
        //--- configure central frequency to ZERO
        //--- disable the line port
        if (rule.type == TerminalDeviceFlowRule.Type.LINE_INGRESS ||
                rule.type == TerminalDeviceFlowRule.Type.LINE_EGRESS) {

            FlowRuleParser frp = new FlowRuleParser(rule);
            String componentName = frp.getPortNumber().toString();

            log.info("Removing LINE FlowRule device {} line port {}",
                    did(), componentName);

            try {
                setLogicalChannel(session, OPERATION_DISABLE, componentName);
            } catch (NetconfException e) {
                log.error("Error disabling the logical channel line side");
                return false;
            }
        }

        //Configuration of CLIENT side, used for OpticalCircuit intents
        //--- configure central frequency to ZERO
        //--- disable the line port
        if (rule.type == TerminalDeviceFlowRule.Type.CLIENT_INGRESS ||
                rule.type == TerminalDeviceFlowRule.Type.CLIENT_EGRESS) {

            String clientPortName;
            String linePortName;
            if (rule.type == TerminalDeviceFlowRule.Type.CLIENT_INGRESS) {
                clientPortName = rule.inPort().toString();
                linePortName = rule.outPort().toString();
            } else {
                clientPortName = rule.outPort().toString();
                linePortName = rule.inPort().toString();
            }

            log.debug("Removing CLIENT FlowRule device {} client port: {}, line port {}",
                    did(), clientPortName, linePortName);

            try {
                setLogicalChannelAssignment(session, OPERATION_DISABLE, clientPortName, linePortName,
                        DEFAULT_ASSIGNMENT_INDEX, DEFAULT_ALLOCATION_INDEX);
            } catch (NetconfException e) {
                log.error("Error disabling the logical channel assignment");
                return false;
            }
        }

        return true;
    }

    private List<FlowRule> fetchLineConnectionFromDevice(String channel, Frequency centralFreq) {
        List<FlowRule> confirmedRules = new ArrayList<>();
        FlowRule cacheAddRule;
        FlowRule cacheDropRule;
        NetconfSession session = getNetconfSession();

        log.debug("fetchOpticalConnectionsFromDevice {} frequency {}", did(), centralFreq);

        //Build the corresponding flow rule as expected
        //Selector including port and ochSignal
        //Treatment including port
        PortNumber inputPortNumber = PortNumber.portNumber(channel);
        PortNumber outputPortNumber = PortNumber.portNumber(channel);

        log.debug("fetchOpticalConnectionsFromDevice {} port {}-{}", did(), inputPortNumber, outputPortNumber);

        TrafficSelector selectorDrop = DefaultTrafficSelector.builder()
                .matchInPort(inputPortNumber)
                .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
                .add(Criteria.matchLambda(toOchSignal(centralFreq, 50.0)))
                .build();

        TrafficTreatment treatmentDrop = DefaultTrafficTreatment.builder()
                .setOutput(outputPortNumber)
                .build();

        TrafficSelector selectorAdd = DefaultTrafficSelector.builder()
                .matchInPort(inputPortNumber)
                .build();

        TrafficTreatment treatmentAdd = DefaultTrafficTreatment.builder()
                .add(Instructions.modL0Lambda(toOchSignal(centralFreq, 50.0)))
                .setOutput(outputPortNumber)
                .build();

        //Retrieved rules and cached rules are considered equal if both selector and treatment are equal
        cacheAddRule = null;
        cacheDropRule = null;
        if (getConnectionCache().size(did()) != 0) {
            cacheDropRule = getConnectionCache().get(did()).stream()
                    .filter(r -> (r.selector().equals(selectorDrop) && r.treatment().equals(treatmentDrop)))
                    .findFirst()
                    .orElse(null);

            cacheAddRule = getConnectionCache().get(did()).stream()
                    .filter(r -> (r.selector().equals(selectorAdd) && r.treatment().equals(treatmentAdd)))
                    .findFirst()
                    .orElse(null);
        }

        //Include the DROP rule to the retrieved rules if found in cache
        if ((cacheDropRule != null)) {
            confirmedRules.add(cacheDropRule);
            log.debug("fetchOpticalConnectionsFromDevice {} DROP LINE rule included in the cache {}",
                    did(), cacheDropRule);
        } else {
            log.warn("fetchOpticalConnectionsFromDevice {} DROP LINE rule not included in cache", did());
        }

        //Include the ADD rule to the retrieved rules if found in cache
        if ((cacheAddRule != null)) {
            confirmedRules.add(cacheAddRule);
            log.debug("fetchOpticalConnectionsFromDevice {} ADD LINE rule included in the cache {}",
                    did(), cacheAddRule.selector());
        } else {
            log.warn("fetchOpticalConnectionsFromDevice {} ADD LINE rule not included in cache", did());
        }

        //If neither Add or Drop rules are present in the cache, remove configuration from the device
        if ((cacheDropRule == null) && (cacheAddRule == null)) {
            log.warn("fetchOpticalConnectionsFromDevice {} ADD and DROP rule not included in the cache", did());

            FlowRule deviceDropRule = DefaultFlowRule.builder()
                    .forDevice(data().deviceId())
                    .makePermanent()
                    .withSelector(selectorDrop)
                    .withTreatment(treatmentDrop)
                    .withCookie(DEFAULT_RULE_COOKIE)
                    .withPriority(DEFAULT_RULE_PRIORITY)
                    .build();

            FlowRule deviceAddRule = DefaultFlowRule.builder()
                    .forDevice(data().deviceId())
                    .makePermanent()
                    .withSelector(selectorAdd)
                    .withTreatment(treatmentAdd)
                    .withCookie(DEFAULT_RULE_COOKIE)
                    .withPriority(DEFAULT_RULE_PRIORITY)
                    .build();

            try {
                //TODO this is not required if allowExternalFlowRules
                TerminalDeviceFlowRule addRule = new TerminalDeviceFlowRule(deviceAddRule, getLinePorts());
                removeFlowRule(session, addRule);

                TerminalDeviceFlowRule dropRule = new TerminalDeviceFlowRule(deviceDropRule, getLinePorts());
                removeFlowRule(session, dropRule);
            } catch (NetconfException e) {
                openConfigError("Error removing LINE rule from device", e);
            }
        }
        return confirmedRules;
    }

    private List<FlowRule> fetchClientConnectionFromDevice(PortNumber clientPortNumber, PortNumber linePortNumber) {
        List<FlowRule> confirmedRules = new ArrayList<>();
        FlowRule cacheAddRule;
        FlowRule cacheDropRule;
        NetconfSession session = getNetconfSession();

        //Build the corresponding flow rule as expected
        //Selector including port
        //Treatment including port

        log.debug("fetchClientConnectionsFromDevice {} client {} line {}", did(), clientPortNumber, linePortNumber);

        TrafficSelector selectorDrop = DefaultTrafficSelector.builder()
                .matchInPort(linePortNumber)
                .build();

        TrafficTreatment treatmentDrop = DefaultTrafficTreatment.builder()
                .setOutput(clientPortNumber)
                .build();

        TrafficSelector selectorAdd = DefaultTrafficSelector.builder()
                .matchInPort(clientPortNumber)
                .build();

        TrafficTreatment treatmentAdd = DefaultTrafficTreatment.builder()
                .setOutput(linePortNumber)
                .build();

        //Retrieved rules and cached rules are considered equal if both selector and treatment are equal
        cacheAddRule = null;
        cacheDropRule = null;
        if (getConnectionCache().size(did()) != 0) {
            cacheDropRule = getConnectionCache().get(did()).stream()
                    .filter(r -> (r.selector().equals(selectorDrop) && r.treatment().equals(treatmentDrop)))
                    .findFirst()
                    .orElse(null);

            cacheAddRule = getConnectionCache().get(did()).stream()
                    .filter(r -> (r.selector().equals(selectorAdd) && r.treatment().equals(treatmentAdd)))
                    .findFirst()
                    .orElse(null);
        }

        //Include the DROP rule to the retrieved rules if found in cache
        if ((cacheDropRule != null)) {
            confirmedRules.add(cacheDropRule);
            log.debug("fetchClientConnectionsFromDevice {} DROP CLIENT rule in the cache {}",
                    did(), cacheDropRule);
        } else {
            log.warn("fetchClientConnectionsFromDevice {} DROP CLIENT rule not found in cache", did());
        }

        //Include the ADD rule to the retrieved rules if found in cache
        if ((cacheAddRule != null)) {
            confirmedRules.add(cacheAddRule);
            log.debug("fetchClientConnectionsFromDevice {} ADD CLIENT rule in the cache {}",
                    did(), cacheAddRule);
        } else {
            log.warn("fetchClientConnectionsFromDevice {} ADD CLIENT rule not found in cache", did());
        }

        if ((cacheDropRule == null) && (cacheAddRule == null)) {
            log.warn("fetchClientConnectionsFromDevice {} ADD and DROP rule not included in the cache", did());

            FlowRule deviceDropRule = DefaultFlowRule.builder()
                    .forDevice(data().deviceId())
                    .makePermanent()
                    .withSelector(selectorDrop)
                    .withTreatment(treatmentDrop)
                    .withCookie(DEFAULT_RULE_COOKIE)
                    .withPriority(DEFAULT_RULE_PRIORITY)
                    .build();

            FlowRule deviceAddRule = DefaultFlowRule.builder()
                    .forDevice(data().deviceId())
                    .makePermanent()
                    .withSelector(selectorAdd)
                    .withTreatment(treatmentAdd)
                    .withCookie(DEFAULT_RULE_COOKIE)
                    .withPriority(DEFAULT_RULE_PRIORITY)
                    .build();

            try {
                //TODO this is not required if allowExternalFlowRules
                TerminalDeviceFlowRule addRule = new TerminalDeviceFlowRule(deviceAddRule, getLinePorts());
                removeFlowRule(session, addRule);

                TerminalDeviceFlowRule dropRule = new TerminalDeviceFlowRule(deviceDropRule, getLinePorts());
                removeFlowRule(session, dropRule);
            } catch (NetconfException e) {
                openConfigError("Error removing CLIENT rule from device", e);
            }
        }
        return confirmedRules;
    }

    /**
     * Fetches list of connections from device.
     *
     * TODO manage allow external flow rules (allowExternalFlowRules)
     * Currently removes from the device all connections that are not currently present in the DeviceConnectionCache.
     *
     * @return connections that are present on the device and in the DeviceConnectionCache.
     */
    private List<FlowRule> fetchConnectionsFromDevice() {
        List<FlowRule> confirmedRules = new ArrayList<>();
        String reply;
        FlowRule cacheAddRule;
        FlowRule cacheDropRule;
        NetconfSession session = getNetconfSession();

        //Get relevant information from the device
        StringBuilder requestFilter = new StringBuilder();
        requestFilter.append("<components xmlns='http://openconfig.net/yang/platform'>");
        requestFilter.append("  <component>");
        requestFilter.append("    <name/>");
        requestFilter.append("    <oc-opt-term:optical-channel " +
                "xmlns:oc-opt-term='http://openconfig.net/yang/terminal-device'>");
        requestFilter.append("      <oc-opt-term:config/>");
        requestFilter.append("    </oc-opt-term:optical-channel>");
        requestFilter.append("  </component>");
        requestFilter.append("</components>");
        requestFilter.append("<terminal-device xmlns='http://openconfig.net/yang/terminal-device'>");
        requestFilter.append("  <logical-channels>");
        requestFilter.append("    <channel>");
        requestFilter.append("      <index/>");
        requestFilter.append("      <config>");
        requestFilter.append("        <admin-state/>");
        requestFilter.append("        <logical-channel-type/>");
        requestFilter.append("      </config>");
        requestFilter.append("      <logical-channel-assignments>");
        requestFilter.append("        <assignment>");
        requestFilter.append("          <config>");
        requestFilter.append("            <logical-channel/>");
        requestFilter.append("          </config>");
        requestFilter.append("        </assignment>");
        requestFilter.append("      </logical-channel-assignments>");
        requestFilter.append("    </channel>");
        requestFilter.append("  </logical-channels>");
        requestFilter.append("</terminal-device>");

        try {
            reply = session.get(requestFilter.toString(), null);
            //log.debug("TRANSPONDER CONNECTIONS - fetchConnectionsFromDevice {} reply {}", did(), reply);
        } catch (NetconfException e) {
            log.error("Failed to retrieve configuration details for device {}", handler().data().deviceId(), e);
            return ImmutableList.of();
        }

        HierarchicalConfiguration cfg = XmlConfigParser.loadXml(new ByteArrayInputStream(reply.getBytes()));

        List<HierarchicalConfiguration> logicalChannels =
                cfg.configurationsAt("data.terminal-device.logical-channels.channel");

        List<HierarchicalConfiguration> components =
                cfg.configurationsAt("data.components.component");

        //Retrieve the ENABLED line ports
        List<String> enabledOpticalChannels = logicalChannels.stream()
                .filter(r -> r.getString("config.logical-channel-type").equals(OC_TYPE_PROT_OTN))
                .filter(r -> r.getString("config.admin-state").equals(OPERATION_ENABLE))
                .map(r -> r.getString("index"))
                .collect(Collectors.toList());

        log.debug("fetchConnectionsFromDevice {} enabledOpticalChannelsIndex {}", did(), enabledOpticalChannels);

        if (enabledOpticalChannels.size() != 0) {
            for (String channel : enabledOpticalChannels) {
                log.debug("fetchOpticalConnectionsFromDevice {} channel {}", did(), channel);

                //Retrieve the corresponding central frequency from the associated component
                //TODO correlate the components instead of relying on naming
                Frequency centralFreq = components.stream()
                        .filter(c -> c.getString("name").equals(PREFIX_CHANNEL + channel))
                        .map(c -> c.getDouble("optical-channel.config.frequency"))
                        .map(c -> Frequency.ofMHz(c))
                        .findFirst()
                        .orElse(null);

                confirmedRules.addAll(fetchLineConnectionFromDevice(channel, centralFreq));
            }
        }

        //Retrieve the ENABLED client ports
        List<String> enabledClientChannels = logicalChannels.stream()
                .filter(r -> r.getString("config.logical-channel-type").equals(OC_TYPE_PROT_ETH))
                .filter(r -> r.getString("config.admin-state").equals(OPERATION_ENABLE))
                .map(r -> r.getString("index"))
                .collect(Collectors.toList());

        log.debug("fetchClientConnectionsFromDevice {} enabledClientChannelsIndex {}", did(), enabledClientChannels);

        if (enabledClientChannels.size() != 0) {
            for (String clientPort : enabledClientChannels) {

                log.debug("fetchClientConnectionsFromDevice {} channel {}", did(), clientPort);

                String linePort = logicalChannels.stream()
                    .filter(r -> r.getString("config.logical-channel-type").equals(OC_TYPE_PROT_ETH))
                    .filter(r -> r.getString("config.admin-state").equals(OPERATION_ENABLE))
                    .filter(r -> r.getString("index").equals(clientPort))
                    .map(r -> r.getString("logical-channel-assignments.assignment.config.logical-channel"))
                    .findFirst()
                    .orElse(null);

                //Build the corresponding flow rule as expected
                //Selector including port
                //Treatment including port
                PortNumber clientPortNumber = PortNumber.portNumber(clientPort);
                PortNumber linePortNumber = PortNumber.portNumber(linePort);

                confirmedRules.addAll(fetchClientConnectionFromDevice(clientPortNumber, linePortNumber));
            }
        }

        //Returns rules that are both on the device and on the cache
        if (confirmedRules.size() != 0) {
            log.info("fetchConnectionsFromDevice {} number of confirmed rules {}", did(), confirmedRules.size());
            return confirmedRules;
        } else {
            return ImmutableList.of();
        }
    }

    /**
     * Convert start and end frequencies to OCh signal.
     *
     * FIXME: supports channel spacing 50 and 100
     *
     * @param central central frequency as double in THz
     * @param width width of the channel arounf the central frequency as double in GHz
     * @return OCh signal
     */
    public static OchSignal toOchSignal(Frequency central, double width) {
        int slots = (int) (width / ChannelSpacing.CHL_12P5GHZ.frequency().asGHz());
        int multiplier = 0;

        double centralAsGHz = central.asGHz();

        if (width == 50) {
            multiplier = (int) ((centralAsGHz - Spectrum.CENTER_FREQUENCY.asGHz())
                    / ChannelSpacing.CHL_50GHZ.frequency().asGHz());

            return new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, multiplier, slots);
        }

        if (width == 100) {
            multiplier = (int) ((centralAsGHz - Spectrum.CENTER_FREQUENCY.asGHz())
                    / ChannelSpacing.CHL_100GHZ.frequency().asGHz());

            return new OchSignal(GridType.DWDM, ChannelSpacing.CHL_100GHZ, multiplier, slots);
        }

        return null;
    }

    private List<PortNumber> getLinePorts() {
        List<PortNumber> linePorts;

        DeviceService deviceService = this.handler().get(DeviceService.class);
        linePorts = deviceService.getPorts(data().deviceId()).stream()
                .filter(p -> p.annotations().value(OdtnDeviceDescriptionDiscovery.PORT_TYPE)
                        .equals(OdtnDeviceDescriptionDiscovery.OdtnPortType.LINE.value()))
                .map(p -> p.number())
                .collect(Collectors.toList());

        return linePorts;

    }
}
