/*
 * Copyright 2014-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.provider.of.device.impl;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.get;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.Port.Type.COPPER;
import static org.onosproject.net.Port.Type.FIBER;
import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDescription;
import static org.onosproject.net.optical.device.OmsPortHelper.omsPortDescription;
import static org.onosproject.net.optical.device.OtuPortHelper.otuPortDescription;
import static org.onosproject.openflow.controller.Dpid.dpid;
import static org.onosproject.openflow.controller.Dpid.uri;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.Timer;

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.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ChassisId;
import org.onlab.util.Frequency;
import org.onlab.util.Spectrum;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.CltSignalType;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.GridType;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.OtuSignalType;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.behaviour.LambdaQuery;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DefaultPortStatistics;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.driver.HandlerBehaviour;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.OpenFlowController;
import org.onosproject.openflow.controller.OpenFlowEventListener;
import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.onosproject.openflow.controller.OpenFlowSwitchListener;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.onosproject.openflow.controller.RoleState;
import org.osgi.service.component.ComponentContext;
import org.projectfloodlight.openflow.protocol.OFCalientPortDescProp;
import org.projectfloodlight.openflow.protocol.OFCalientPortDescPropOptical;
import org.projectfloodlight.openflow.protocol.OFCalientPortDescStatsEntry;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFErrorType;
import org.projectfloodlight.openflow.protocol.OFExpPort;
import org.projectfloodlight.openflow.protocol.OFExpPortDescPropOpticalTransport;
import org.projectfloodlight.openflow.protocol.OFExpPortOpticalTransportLayerEntry;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFObject;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortDescPropOpticalTransport;
import org.projectfloodlight.openflow.protocol.OFPortFeatures;
import org.projectfloodlight.openflow.protocol.OFPortMod;
import org.projectfloodlight.openflow.protocol.OFPortOptical;
import org.projectfloodlight.openflow.protocol.OFPortOpticalTransportLayerClass;
import org.projectfloodlight.openflow.protocol.OFPortOpticalTransportSignalType;
import org.projectfloodlight.openflow.protocol.OFPortReason;
import org.projectfloodlight.openflow.protocol.OFPortState;
import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
import org.projectfloodlight.openflow.protocol.OFPortStatsReply;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.PortSpeed;
import org.slf4j.Logger;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * Provider which uses an OpenFlow controller to detect network
 * infrastructure devices.
 */
@Component(immediate = true)
public class OpenFlowDeviceProvider extends AbstractProvider implements DeviceProvider {

    private static final Logger LOG = getLogger(OpenFlowDeviceProvider.class);

    //TODO consider renaming KBPS and MBPS (as they are used to convert by division)
    private static final long KBPS = 1_000;
    private static final long MBPS = 1_000 * 1_000;
    private static final Frequency FREQ50 = Frequency.ofGHz(50);
    private static final Frequency FREQ191_7 = Frequency.ofGHz(191_700);
    private static final Frequency FREQ4_4 = Frequency.ofGHz(4_400);

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceProviderRegistry providerRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected OpenFlowController controller;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ComponentConfigService cfgService;

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

    private DeviceProviderService providerService;

    private final InternalDeviceProvider listener = new InternalDeviceProvider();

    private static final String POLL_PROP_NAME = "portStatsPollFrequency";
    private static final int POLL_INTERVAL = 5;
    @Property(name = POLL_PROP_NAME, intValue = POLL_INTERVAL,
    label = "Frequency (in seconds) for polling switch Port statistics")
    private int portStatsPollFrequency = POLL_INTERVAL;

    private final Timer timer = new Timer("onos-openflow-portstats-collector");

    private HashMap<Dpid, PortStatsCollector> collectors = Maps.newHashMap();

    /**
     * Creates an OpenFlow device provider.
     */
    public OpenFlowDeviceProvider() {
        super(new ProviderId("of", "org.onosproject.provider.openflow"));
    }

    @Activate
    public void activate(ComponentContext context) {
        cfgService.registerProperties(getClass());
        providerService = providerRegistry.register(this);
        controller.addListener(listener);
        controller.addEventListener(listener);

        modified(context);

        connectInitialDevices();
        LOG.info("Started");
    }

    @Deactivate
    public void deactivate(ComponentContext context) {
        cfgService.unregisterProperties(getClass(), false);
        listener.disable();
        controller.removeListener(listener);
        providerRegistry.unregister(this);
        collectors.values().forEach(PortStatsCollector::stop);
        collectors.clear();
        providerService = null;
        LOG.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
        int newPortStatsPollFrequency;
        try {
            String s = get(properties, POLL_PROP_NAME);
            newPortStatsPollFrequency = isNullOrEmpty(s) ? portStatsPollFrequency : Integer.parseInt(s.trim());

        } catch (NumberFormatException | ClassCastException e) {
            newPortStatsPollFrequency = portStatsPollFrequency;
        }

        if (newPortStatsPollFrequency != portStatsPollFrequency) {
            portStatsPollFrequency = newPortStatsPollFrequency;
            collectors.values().forEach(psc -> psc.adjustPollInterval(portStatsPollFrequency));
        }

        LOG.info("Settings: portStatsPollFrequency={}", portStatsPollFrequency);
    }

    private void connectInitialDevices() {
        for (OpenFlowSwitch sw : controller.getSwitches()) {
            try {
                listener.switchAdded(new Dpid(sw.getId()));
            } catch (Exception e) {
                LOG.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage());
                LOG.debug("Error details:", e);
                // disconnect to trigger switch-add later
                sw.disconnectSwitch();
            }
            PortStatsCollector psc = new PortStatsCollector(timer, sw, portStatsPollFrequency);
            psc.start();
            collectors.put(new Dpid(sw.getId()), psc);
        }
    }

    @Override
    public boolean isReachable(DeviceId deviceId) {
        OpenFlowSwitch sw = controller.getSwitch(dpid(deviceId.uri()));
        return sw != null && sw.isConnected();
    }

    @Override
    public void triggerProbe(DeviceId deviceId) {
        LOG.debug("Triggering probe on device {}", deviceId);

        final Dpid dpid = dpid(deviceId.uri());
        OpenFlowSwitch sw = controller.getSwitch(dpid);
        if (sw == null || !sw.isConnected()) {
            LOG.error("Failed to probe device {} on sw={}", deviceId, sw);
            providerService.deviceDisconnected(deviceId);
            return;
        } else {
            LOG.trace("Confirmed device {} connection", deviceId);
        }

        // Prompt an update of port information. We can use any XID for this.
        OFFactory fact = sw.factory();
        switch (fact.getVersion()) {
            case OF_10:
                sw.sendMsg(fact.buildFeaturesRequest().setXid(0).build());
                break;
            case OF_13:
                sw.sendMsg(fact.buildPortDescStatsRequest().setXid(0).build());
                break;
            default:
                LOG.warn("Unhandled protocol version");
        }
    }

    @Override
    public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
        switch (newRole) {
            case MASTER:
                controller.setRole(dpid(deviceId.uri()), RoleState.MASTER);
                break;
            case STANDBY:
                controller.setRole(dpid(deviceId.uri()), RoleState.EQUAL);
                break;
            case NONE:
                controller.setRole(dpid(deviceId.uri()), RoleState.SLAVE);
                break;
            default:
                LOG.error("Unknown Mastership state : {}", newRole);

        }
        LOG.debug("Accepting mastership role change to {} for device {}", newRole, deviceId);
    }

    @Override
    public void changePortState(DeviceId deviceId, PortNumber portNumber,
                                boolean enable) {
        final Dpid dpid = dpid(deviceId.uri());
        OpenFlowSwitch sw = controller.getSwitch(dpid);
        if (sw == null || !sw.isConnected()) {
            LOG.error("Failed to change portState on device {}", deviceId);
            return;
        }
        OFPortMod.Builder pmb = sw.factory().buildPortMod();
        OFPort port = OFPort.of((int) portNumber.toLong());
        pmb.setPortNo(port);
        if (enable) {
            pmb.setConfig(0x0); // port_down bit 0
        } else {
            pmb.setConfig(0x1); // port_down bit 1
        }
        pmb.setMask(0x1);
        pmb.setAdvertise(0x0);
        for (OFPortDesc pd : sw.getPorts()) {
            if (pd.getPortNo().equals(port)) {
                pmb.setHwAddr(pd.getHwAddr());
                break;
            }
        }
        sw.sendMsg(Collections.singletonList(pmb.build()));
    }

    private void pushPortMetrics(Dpid dpid, List<OFPortStatsEntry> portStatsEntries) {
        DeviceId deviceId = DeviceId.deviceId(Dpid.uri(dpid));
        Collection<PortStatistics> stats =
                buildPortStatistics(deviceId, ImmutableList.copyOf(portStatsEntries));
        providerService.updatePortStatistics(deviceId, stats);
    }

    private Collection<PortStatistics> buildPortStatistics(DeviceId deviceId,
                                                           List<OFPortStatsEntry> entries) {
        HashSet<PortStatistics> stats = Sets.newHashSet();

        for (OFPortStatsEntry entry : entries) {
            try {
                if (entry == null || entry.getPortNo() == null || entry.getPortNo().getPortNumber() < 0) {
                    continue;
                }
                DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder();
                DefaultPortStatistics stat = builder.setDeviceId(deviceId)
                        .setPort(entry.getPortNo().getPortNumber())
                        .setPacketsReceived(entry.getRxPackets().getValue())
                        .setPacketsSent(entry.getTxPackets().getValue())
                        .setBytesReceived(entry.getRxBytes().getValue())
                        .setBytesSent(entry.getTxBytes().getValue())
                        .setPacketsRxDropped(entry.getRxDropped().getValue())
                        .setPacketsTxDropped(entry.getTxDropped().getValue())
                        .setPacketsRxErrors(entry.getRxErrors().getValue())
                        .setPacketsTxErrors(entry.getTxErrors().getValue())
                        .setDurationSec(entry.getVersion() == OFVersion.OF_10 ? 0 : entry.getDurationSec())
                        .setDurationNano(entry.getVersion() == OFVersion.OF_10 ? 0 : entry.getDurationNsec())
                        .build();

                stats.add(stat);
            } catch (Exception e) {
                LOG.warn("Unable to process port stats", e);
            }
        }

        return Collections.unmodifiableSet(stats);
    }

    private class InternalDeviceProvider implements OpenFlowSwitchListener, OpenFlowEventListener {

        private HashMap<Dpid, List<OFPortStatsEntry>> portStatsReplies = new HashMap<>();
        private boolean isDisabled = false;

        @Override
        public void switchAdded(Dpid dpid) {
            if (providerService == null) {
                return;
            }
            DeviceId did = deviceId(uri(dpid));
            OpenFlowSwitch sw = controller.getSwitch(dpid);
            if (sw == null) {
                LOG.error("Switch {} is not found", dpid);
                return;
            }

            ChassisId cId = new ChassisId(dpid.value());

            DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder()
                    .set(AnnotationKeys.PROTOCOL, sw.factory().getVersion().toString())
                    .set(AnnotationKeys.CHANNEL_ID, sw.channelId())
                    .set(AnnotationKeys.MANAGEMENT_ADDRESS, sw.channelId().split(":")[0]);

            Driver driver = driverService.getDriver(sw.manufacturerDescription(),
                    sw.hardwareDescription(),
                    sw.softwareDescription());
            // FIXME: The following breaks the STC tests and will require to be revisited.
//            if (driver != null) {
//                annotationsBuilder.set(AnnotationKeys.DRIVER, driver.name());
//            }

            SparseAnnotations annotations = annotationsBuilder.build();

            DeviceDescription description =
                    new DefaultDeviceDescription(did.uri(), sw.deviceType(),
                                                 sw.manufacturerDescription(),
                                                 sw.hardwareDescription(),
                                                 sw.softwareDescription(),
                                                 sw.serialNumber(),
                                                 cId, annotations);
            providerService.deviceConnected(did, description);
            providerService.updatePorts(did, buildPortDescriptions(sw));

            PortStatsCollector psc = new PortStatsCollector(timer, sw, portStatsPollFrequency);
            stopCollectorIfNeeded(collectors.put(dpid, psc));
            psc.start();

            //figure out race condition for collectors.remove() and collectors.put()
            if (controller.getSwitch(dpid) == null) {
                switchRemoved(dpid);
            }
        }

        private void stopCollectorIfNeeded(PortStatsCollector collector) {
            if (collector != null) {
                collector.stop();
            }
        }

        @Override
        public void switchRemoved(Dpid dpid) {
            stopCollectorIfNeeded(collectors.remove(dpid));
            if (providerService == null) {
                return;
            }
            providerService.deviceDisconnected(deviceId(uri(dpid)));
        }

        @Override
        public void switchChanged(Dpid dpid) {
            LOG.debug("switchChanged({})", dpid);
            if (providerService == null) {
                return;
            }
            DeviceId did = deviceId(uri(dpid));
            OpenFlowSwitch sw = controller.getSwitch(dpid);
            if (sw == null) {
                LOG.error("Switch {} is not found", dpid);
                return;
            }
            final List<PortDescription> ports = buildPortDescriptions(sw);
            LOG.debug("switchChanged({}) {}", did, ports);
            providerService.updatePorts(did, ports);
        }

        @Override
        public void portChanged(Dpid dpid, OFPortStatus status) {
            LOG.debug("portChanged({},{})", dpid, status);
            PortDescription portDescription = buildPortDescription(status);
            providerService.portStatusChanged(deviceId(uri(dpid)), portDescription);
        }

        @Override
        public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
            LOG.debug("receivedRoleReply({},{},{})", dpid, requested, response);
            MastershipRole request = roleOf(requested);
            MastershipRole reply = roleOf(response);
            providerService.receivedRoleReply(deviceId(uri(dpid)), request, reply);
        }

        /**
         * Translates a RoleState to the corresponding MastershipRole.
         *
         * @param response role state
         * @return a MastershipRole
         */
        private MastershipRole roleOf(RoleState response) {
            switch (response) {
                case MASTER:
                    return MastershipRole.MASTER;
                case EQUAL:
                    return MastershipRole.STANDBY;
                case SLAVE:
                    return MastershipRole.NONE;
                default:
                    LOG.warn("unknown role {}", response);
                    return null;
            }
        }

        /**
         * Builds a list of port descriptions for a given list of ports.
         *
         * @return list of portdescriptions
         */
        private List<PortDescription> buildPortDescriptions(OpenFlowSwitch sw) {
            final List<PortDescription> portDescs = new ArrayList<>(sw.getPorts().size());
            if (!((Device.Type.ROADM.equals(sw.deviceType())) ||
                    (Device.Type.OTN.equals(sw.deviceType())))) {
                  sw.getPorts().forEach(port -> portDescs.add(buildPortDescription(port)));
            }

            OpenFlowOpticalSwitch opsw;
            switch (sw.deviceType()) {
                case ROADM:
                case OTN:
                    opsw = (OpenFlowOpticalSwitch) sw;
                    List<OFPortDesc> ports = opsw.getPorts();
                    LOG.debug("SW ID {} , ETH- ODU CLT Ports {}", opsw.getId(), ports);
                    // ODU client ports are reported as ETH
                    ports.forEach(port -> portDescs.add(buildOduCltPortDescription(port)));

                    opsw.getPortTypes().forEach(type -> {
                    List<? extends OFObject> portsOf = opsw.getPortsOf(type);
                    LOG.debug("Ports Of{}", portsOf);
                    portsOf.forEach(
                        op -> {
                            portDescs.add(buildPortDescription(type, op, opsw));
                        }
                     );
                    });
                    break;
                case FIBER_SWITCH:
                    opsw = (OpenFlowOpticalSwitch) sw;
                    opsw.getPortTypes().forEach(type -> {
                        opsw.getPortsOf(type).forEach(
                                op -> {
                                    portDescs.add(buildPortDescription((OFCalientPortDescStatsEntry) op));
                                }
                        );
                    });
                    break;
                default:
                    break;
            }

            return portDescs;
        }

        private PortDescription buildOduCltPortDescription(OFPortDesc port) {
            PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
            boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) &&
                              !port.getConfig().contains(OFPortConfig.PORT_DOWN);
            Long portSpeedInMbps = portSpeed(port);
            CltSignalType sigType = null;

            switch (portSpeedInMbps.toString()) {
                case "1000":
                    sigType = CltSignalType.CLT_1GBE;
                    break;
                case "10000":
                    sigType = CltSignalType.CLT_10GBE;
                    break;
                case "40000":
                    sigType = CltSignalType.CLT_40GBE;
                    break;
                case "100000":
                    sigType = CltSignalType.CLT_100GBE;
                    break;
                default:
                    throw new RuntimeException("Un recognize OduClt speed: " + portSpeedInMbps.toString());
            }

            SparseAnnotations annotations = buildOduCltAnnotation(port);
            return oduCltPortDescription(portNo, enabled, sigType, annotations);
        }

        private SparseAnnotations buildOduCltAnnotation(OFPortDesc port) {
            SparseAnnotations annotations = null;
            String portName = Strings.emptyToNull(port.getName());
            if (portName != null) {
                 annotations = DefaultAnnotations.builder()
                        .set(AnnotationKeys.PORT_NAME, portName)
                        .set(AnnotationKeys.STATIC_PORT, Boolean.TRUE.toString()).build();
            }
            return annotations;
        }

        private PortDescription buildPortDescription(PortDescPropertyType ptype, OFObject port,
                OpenFlowOpticalSwitch opsw) {
            if (port instanceof OFPortOptical) {
                return buildPortDescription(ptype, (OFPortOptical) port, opsw);
            }
            return buildPortDescription(ptype, (OFExpPort) port);
        }

        private boolean matchingOtuPortSignalTypes(OFPortOpticalTransportSignalType sigType,
                OduSignalType oduSignalType) {
            switch (sigType) {
            case OTU2:
                if (oduSignalType == OduSignalType.ODU2) {
                    return true;
                }
                break;
            case OTU4:
                if (oduSignalType == OduSignalType.ODU4) {
                    return true;
                }
                break;
            default:
                break;
            }
            return false;
        }
        /**
         * Build a portDescription from a given a port description describing some
         * Optical port.
         *
         * @param ptype description property type.
         * @param port the port to build from.
         * @return portDescription for the port.
         */
        private PortDescription buildPortDescription(PortDescPropertyType ptype, OFExpPort port) {
            PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
            boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN)
                    && !port.getConfig().contains(OFPortConfig.PORT_DOWN);
            SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString());

            OFExpPortDescPropOpticalTransport firstProp = port.getProperties().get(0);
            OFPortOpticalTransportSignalType sigType = firstProp.getPortSignalType();

            PortDescription portDes = null;
            switch (sigType) {
            case OMSN:
                portDes = omsPortDescription(portNo, enabled,
                        FREQ191_7, FREQ191_7.add(FREQ4_4), FREQ50, annotations);
                break;
            case OCH:
                OFExpPortOpticalTransportLayerEntry entry = firstProp.getFeatures().get(0).getValue().get(0);
                OFPortOpticalTransportLayerClass layerClass =  entry.getLayerClass();
                if (!OFPortOpticalTransportLayerClass.ODU.equals(layerClass)) {
                    LOG.error("Unsupported layer Class {} ", layerClass);
                    return null;
                }

                // convert to ONOS OduSignalType
                OduSignalType oduSignalType = OpenFlowDeviceValueMapper.
                        lookupOduSignalType((byte) entry.getSignalType());
                //OchSignal is needed for OchPortDescription constructor,
                //yet not relevant for tunable OCH port, creating with default parameters
                OchSignal signalId = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 1, 1);

                portDes = ochPortDescription(portNo, enabled,
                                             oduSignalType, true,
                                             signalId, annotations);

                break;
            case OTU2:
            case OTU4:
                entry = firstProp.getFeatures().get(0).getValue().get(0);
                layerClass =  entry.getLayerClass();
                if (!OFPortOpticalTransportLayerClass.ODU.equals(layerClass)) {
                    LOG.error("Unsupported layer Class {} ", layerClass);
                    return null;
                }

                // convert to ONOS OduSignalType
                OduSignalType oduSignalTypeOtuPort = OpenFlowDeviceValueMapper.
                        lookupOduSignalType((byte) entry.getSignalType());
                if (!matchingOtuPortSignalTypes(sigType, oduSignalTypeOtuPort)) {
                    LOG.error("Wrong oduSignalType {} for OTU Port sigType {} ", oduSignalTypeOtuPort, sigType);
                    return null;
                }
                OtuSignalType otuSignalType =
                        ((sigType == OFPortOpticalTransportSignalType.OTU2) ? OtuSignalType.OTU2 :
                            OtuSignalType.OTU4);
                portDes = otuPortDescription(portNo, enabled, otuSignalType, annotations);
                break;
            default:
                break;
            }

            return portDes;
        }

        /**
         * Creates an annotation for the port name if one is available.
         *
         * @param portName the port name
         * @param portMac the port mac
         * @return annotation containing the port name if one is found,
         *         null otherwise
         */
        private SparseAnnotations makePortAnnotation(String portName, String portMac) {
            SparseAnnotations annotations = null;
            String pName = Strings.emptyToNull(portName);
            String pMac = Strings.emptyToNull(portMac);
            if (portName != null) {
                annotations = DefaultAnnotations.builder()
                        .set(AnnotationKeys.PORT_NAME, pName)
                        .set(AnnotationKeys.PORT_MAC, pMac).build();
            }
            return annotations;
        }

        /**
         * Build a portDescription from a given Ethernet port description.
         *
         * @param port the port to build from.
         * @return portDescription for the port.
         */
        private PortDescription buildPortDescription(OFPortDesc port) {
            PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
            boolean enabled =
                    !port.getState().contains(OFPortState.LINK_DOWN) &&
                            !port.getConfig().contains(OFPortConfig.PORT_DOWN);
            Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER;
            SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString());
            return new DefaultPortDescription(portNo, enabled, type,
                                              portSpeed(port), annotations);
        }

        /**
         * Build a portDescription from a given a port description describing some
         * Optical port.
         *
         * @param port description property type.
         * @param port the port to build from.
         * @return portDescription for the port.
         */
        private PortDescription buildPortDescription(PortDescPropertyType ptype, OFPortOptical port,
                OpenFlowOpticalSwitch opsw) {
            checkArgument(!port.getDesc().isEmpty());

            // Minimally functional fixture. This needs to be fixed as we add better support.
            PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());

            boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN)
                    && !port.getConfig().contains(OFPortConfig.PORT_DOWN);
            SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString());

            if (port.getVersion() == OFVersion.OF_13
                    && ptype == PortDescPropertyType.OPTICAL_TRANSPORT) {
                // At this point, not much is carried in the optical port message.
                LOG.debug("Optical transport port message {}", port.toString());
            } else {
                // removable once 1.4+ support complete.
                LOG.debug("Unsupported optical port properties");
            }

            OFPortDescPropOpticalTransport desc = port.getDesc().get(0);
            switch (desc.getPortSignalType()) {
                // FIXME: use constants once loxi has full optical extensions
                case 2:     // OMS port
                    // Assume complete optical spectrum and 50 GHz grid
                    // LINC-OE is only supported optical OF device for now
                    Set<OchSignal> signals = null;
                    if (opsw instanceof HandlerBehaviour) {
                        DriverHandler driverHandler = ((HandlerBehaviour) opsw).handler();
                        if (driverHandler != null && driverHandler.hasBehaviour(LambdaQuery.class)) {
                            try {
                                signals = driverHandler.behaviour(LambdaQuery.class).queryLambdas(portNo);
                            } catch (NullPointerException e) {
                                signals = null;
                            }
                        }
                    }
                    Frequency minFreq;
                    Frequency maxFreq;
                    Frequency channelSpacing;
                    if (signals == null || signals.isEmpty()) {
                        minFreq = Spectrum.U_BAND_MIN;
                        maxFreq = Spectrum.O_BAND_MAX;
                        channelSpacing = Frequency.ofGHz(50);
                    } else {
                        Comparator<OchSignal> compare =
                                (OchSignal a, OchSignal b) -> a.spacingMultiplier() - b.spacingMultiplier();
                        OchSignal minOch = Collections.min(signals, compare);
                        OchSignal maxOch = Collections.max(signals, compare);
                        minFreq = minOch.centralFrequency();
                        maxFreq = maxOch.centralFrequency();
                        channelSpacing = minOch.channelSpacing().frequency();
                    }
                    return omsPortDescription(portNo, enabled, minFreq,
                            maxFreq, channelSpacing, annotations);
                case 5:     // OCH port
                    OchSignal signal = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 0, 4);
                    return ochPortDescription(portNo, enabled, OduSignalType.ODU4,
                            true, signal, annotations);
                default:
                    break;
            }

            return new DefaultPortDescription(portNo, enabled, FIBER, 0, annotations);
        }

        /**
         * Build a portDescription from a given port description describing a fiber switch optical port.
         *
         * @param port description property type.
         * @param port the port to build from.
         * @return portDescription for the port.
         */
        private PortDescription buildPortDescription(OFCalientPortDescStatsEntry port) {
            PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());

            // Use the alias name if it's available
            String name = port.getName();
            List<OFCalientPortDescProp> props = port.getProperties();
            if (props != null && !props.isEmpty()) {
                OFCalientPortDescPropOptical propOptical = (OFCalientPortDescPropOptical) props.get(0);
                if (propOptical != null) {
                    name = propOptical.getInAlias();
                }
            }

            // FIXME when Calient OF agent reports port status
            boolean enabled = true;
            SparseAnnotations annotations = makePortAnnotation(name, port.getHwAddr().toString());

            // S160 data sheet
            // Wavelength range: 1260 - 1630 nm, grid is irrelevant for this type of switch
            return omsPortDescription(portNo, enabled,
                    Spectrum.U_BAND_MIN, Spectrum.O_BAND_MAX, Frequency.ofGHz(100), annotations);
        }

        private PortDescription buildPortDescription(OFPortStatus status) {
            OFPortDesc port = status.getDesc();
            if (status.getReason() != OFPortReason.DELETE) {
                return buildPortDescription(port);
            } else {
                PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
                Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER;
                SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString());
                return new DefaultPortDescription(portNo, false, type,
                                                  portSpeed(port), annotations);
            }
        }

        private long portSpeed(OFPortDesc port) {
            if (port.getVersion() == OFVersion.OF_13) {
                // Note: getCurrSpeed() returns a value in kbps (this also applies to OF_11 and OF_12)
                return port.getCurrSpeed() / KBPS;
            }

            PortSpeed portSpeed = PortSpeed.SPEED_NONE;
            for (OFPortFeatures feat : port.getCurr()) {
                portSpeed = PortSpeed.max(portSpeed, feat.getPortSpeed());
            }
            return portSpeed.getSpeedBps() / MBPS;
        }

        @Override
        public void handleMessage(Dpid dpid, OFMessage msg) {
            if (isDisabled) {
                return;
            }

            try {
                switch (msg.getType()) {
                    case STATS_REPLY:
                        if (((OFStatsReply) msg).getStatsType() == OFStatsType.PORT) {
                            OFPortStatsReply portStatsReply = (OFPortStatsReply) msg;
                            List<OFPortStatsEntry> portStatsReplyList = portStatsReplies.get(dpid);
                            if (portStatsReplyList == null) {
                                portStatsReplyList = Lists.newCopyOnWriteArrayList();
                            }
                            portStatsReplyList.addAll(portStatsReply.getEntries());
                            portStatsReplies.put(dpid, portStatsReplyList);
                            if (!portStatsReply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
                                List<OFPortStatsEntry> statsEntries = portStatsReplies.get(dpid);
                                if (statsEntries != null) {
                                    pushPortMetrics(dpid, statsEntries);
                                    statsEntries.clear();
                                }
                            }
                        } else if (((OFStatsReply) msg).getStatsType() == OFStatsType.EXPERIMENTER) {
                            OpenFlowSwitch sw = controller.getSwitch(dpid);
                            if (sw == null) {
                                LOG.error("Switch {} is not found", dpid);
                                break;
                            }
                            if (sw instanceof OpenFlowOpticalSwitch) {
                                // Optical switch uses experimenter stats message to update power
                                List<PortDescription> portDescs =
                                        ((OpenFlowOpticalSwitch) sw).processExpPortStats(msg);
                                if (!portDescs.isEmpty()) {
                                    providerService.updatePorts(DeviceId.deviceId(Dpid.uri(dpid)), portDescs);
                                }
                            }
                        }
                        break;
                    case ERROR:
                        if (((OFErrorMsg) msg).getErrType() == OFErrorType.PORT_MOD_FAILED) {
                            LOG.error("port mod failed");
                        }
                    default:
                        break;
                }
            } catch (IllegalStateException e) {
                // system is shutting down and the providerService is no longer
                // valid. Messages cannot be processed.
            }
        }

        private void disable() {
            isDisabled = true;
        }
    }


}
