/*
 * Copyright 2015-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.rest.resources;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.onlab.packet.ChassisId;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.Frequency;
import org.onlab.util.Spectrum;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.GridType;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.Link;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OduCltPort;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.OmsPort;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.OduCltPortDescription;
import org.onosproject.net.device.OmsPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.optical.OchPort;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
import static org.onosproject.net.optical.device.OpticalDeviceServiceView.opticalView;

/**
 * Provider of devices and links parsed from a JSON configuration structure.
 *
 * @deprecated in 1.5.0 (Falcon)
 */
@Deprecated
class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider {

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

    private static final ProviderId PID =
            new ProviderId("cfg", "org.onosproject.rest", true);

    private static final String UNKNOWN = "unknown";

    // C-band has 4.4 THz (4,400 GHz) total bandwidth
    private static final Frequency TOTAL = Frequency.ofGHz(4_400);

    private CountDownLatch deviceLatch;

    private final JsonNode cfg;
    private final DeviceService deviceService;

    private final DeviceProviderRegistry deviceProviderRegistry;
    private final LinkProviderRegistry linkProviderRegistry;
    private final HostProviderRegistry hostProviderRegistry;

    private DeviceProviderService deviceProviderService;
    private LinkProviderService linkProviderService;
    private HostProviderService hostProviderService;

    private DeviceListener deviceEventCounter = new DeviceEventCounter();
    private List<ConnectPoint> connectPoints = Lists.newArrayList();
    private Map<ConnectPoint, PortDescription> descriptions = Maps.newHashMap();

    /**
     * Creates a new configuration provider.
     *
     * @param cfg                    JSON configuration
     * @param deviceService          device service
     * @param deviceProviderRegistry device provider registry
     * @param linkProviderRegistry   link provider registry
     * @param hostProviderRegistry   host provider registry
     */
    ConfigProvider(JsonNode cfg,
                   DeviceService deviceService,
                   DeviceProviderRegistry deviceProviderRegistry,
                   LinkProviderRegistry linkProviderRegistry,
                   HostProviderRegistry hostProviderRegistry) {
        this.cfg = checkNotNull(cfg, "Configuration cannot be null");
        this.deviceService = opticalView(checkNotNull(deviceService, "Device service cannot be null"));
        this.deviceProviderRegistry = checkNotNull(deviceProviderRegistry, "Device provider registry cannot be null");
        this.linkProviderRegistry = checkNotNull(linkProviderRegistry, "Link provider registry cannot be null");
        this.hostProviderRegistry = checkNotNull(hostProviderRegistry, "Host provider registry cannot be null");
    }

    /**
     * Parses the given JSON and provides links as configured.
     */
    void parse() {
        try {
            register();
            parseDevices();
            parseLinks();
            parseHosts();
            addMissingPorts();
        } finally {
            unregister();
        }
    }

    private void register() {
        deviceProviderService = deviceProviderRegistry.register(this);
        linkProviderService = linkProviderRegistry.register(this);
        hostProviderService = hostProviderRegistry.register(this);
    }

    private void unregister() {
        deviceProviderRegistry.unregister(this);
        linkProviderRegistry.unregister(this);
        hostProviderRegistry.unregister(this);
    }

    // Parses the given JSON and provides devices.
    private void parseDevices() {
        try {
            JsonNode nodes = cfg.get("devices");
            if (nodes != null) {
                prepareForDeviceEvents(nodes.size());
                for (JsonNode node : nodes) {
                    parseDevice(node);

                    // FIXME: hack to make sure device attributes take
                    // This will be fixed when GossipDeviceStore uses ECM
                    parseDevice(node);
                }
            }
        } finally {
            waitForDeviceEvents();
        }
    }

    // Parses the given node with device data and supplies the device.
    private void parseDevice(JsonNode node) {
        URI uri = URI.create(get(node, "uri"));
        Device.Type type = Device.Type.valueOf(get(node, "type", "SWITCH"));
        String mfr = get(node, "mfr", UNKNOWN);
        String hw = get(node, "hw", UNKNOWN);
        String sw = get(node, "sw", UNKNOWN);
        String serial = get(node, "serial", UNKNOWN);
        ChassisId cid = new ChassisId(get(node, "mac", "000000000000"));
        SparseAnnotations annotations = annotations(node.get("annotations"));

        DeviceDescription desc =
                new DefaultDeviceDescription(uri, type, mfr, hw, sw, serial,
                                             cid, annotations);
        DeviceId deviceId = deviceId(uri);
        deviceProviderService.deviceConnected(deviceId, desc);

        JsonNode ports = node.get("ports");
        if (ports != null) {
            parsePorts(deviceId, ports);
        }
    }

    // Parses the given node with list of device ports.
    private void parsePorts(DeviceId deviceId, JsonNode nodes) {
        List<PortDescription> ports = new ArrayList<>();
        for (JsonNode node : nodes) {
            ports.add(parsePort(deviceId, node));
        }
        deviceProviderService.updatePorts(deviceId, ports);
    }

    // Parses the given node with port information.
    private PortDescription parsePort(DeviceId deviceId, JsonNode node) {
        Port.Type type = Port.Type.valueOf(node.path("type").asText("COPPER"));
        // TL1-based ports have a name
        PortNumber port = null;
        if (node.has("name")) {
            for (Port p : deviceService.getPorts(deviceId)) {
                if (p.number().name().equals(node.get("name").asText())) {
                    port = p.number();
                    break;
                }
            }
        } else {
            port = portNumber(node.path("port").asLong(0));
        }

        if (port == null) {
            log.error("Cannot find port given in node {}", node);
            return null;
        }

        String portName = Strings.emptyToNull(port.name());
        SparseAnnotations annotations  = null;
        if (portName != null) {
            annotations = DefaultAnnotations.builder()
                    .set(AnnotationKeys.PORT_NAME, portName).build();
        }
        switch (type) {
            case COPPER:
                return new DefaultPortDescription(port, node.path("enabled").asBoolean(true),
                                                  type, node.path("speed").asLong(1_000),
                                                  annotations);
            case FIBER:
                // Currently, assume OMS when FIBER. Provide sane defaults.
                annotations = annotations(node.get("annotations"));
                return new OmsPortDescription(port, node.path("enabled").asBoolean(true),
                        Spectrum.CENTER_FREQUENCY, Spectrum.CENTER_FREQUENCY.add(TOTAL),
                                              Frequency.ofGHz(100), annotations);
            case ODUCLT:
                annotations = annotations(node.get("annotations"));
                OduCltPort oduCltPort = (OduCltPort) deviceService.getPort(deviceId, port);
                return new OduCltPortDescription(port, node.path("enabled").asBoolean(true),
                        oduCltPort.signalType(), annotations);
            case OCH:
                annotations = annotations(node.get("annotations"));
                OchPort ochPort = (OchPort) deviceService.getPort(deviceId, port);
                return ochPortDescription(port, node.path("enabled").asBoolean(true),
                        ochPort.signalType(), ochPort.isTunable(),
                        ochPort.lambda(), annotations);
            case OMS:
                annotations = annotations(node.get("annotations"));
                OmsPort omsPort = (OmsPort) deviceService.getPort(deviceId, port);
                return new OmsPortDescription(port, node.path("enabled").asBoolean(true),
                        omsPort.minFrequency(), omsPort.maxFrequency(), omsPort.grid(), annotations);
            default:
                log.warn("{}: Unsupported Port Type");
        }
        return new DefaultPortDescription(port, node.path("enabled").asBoolean(true),
                                          type, node.path("speed").asLong(1_000),
                                          annotations);
    }

    // Parses the given JSON and provides links as configured.
    private void parseLinks() {
        JsonNode nodes = cfg.get("links");
        if (nodes != null) {
            for (JsonNode node : nodes) {
                parseLink(node, false);
                if (!node.has("halfplex")) {
                    parseLink(node, true);
                }
            }
        }
    }

    // Parses the given node with link data and supplies the link.
    private void parseLink(JsonNode node, boolean reverse) {
        ConnectPoint src = connectPoint(get(node, "src"));
        ConnectPoint dst = connectPoint(get(node, "dst"));
        Link.Type type = Link.Type.valueOf(get(node, "type", "DIRECT"));
        SparseAnnotations annotations = annotations(node.get("annotations"));
        // take annotations to update optical ports with correct attributes.
        updatePorts(src, dst, annotations);
        DefaultLinkDescription desc = reverse ?
                new DefaultLinkDescription(dst, src, type, annotations) :
                new DefaultLinkDescription(src, dst, type, annotations);
        linkProviderService.linkDetected(desc);

        connectPoints.add(src);
        connectPoints.add(dst);
    }

    private void updatePorts(ConnectPoint src, ConnectPoint dst, SparseAnnotations annotations) {
        final String linkType = annotations.value("optical.type");
        if ("cross-connect".equals(linkType)) {
            String value = annotations.value("bandwidth").trim();
            try {
                double bw = Double.parseDouble(value);
                updateOchPort(bw, src, dst);
            } catch (NumberFormatException e) {
                log.warn("Invalid bandwidth ({}), can't configure port(s)", value);
                return;
            }
        } else if ("WDM".equals(linkType)) {
            String value = annotations.value("optical.waves").trim();
            try {
                int numChls = Integer.parseInt(value);
                updateOmsPorts(numChls, src, dst);
            } catch (NumberFormatException e) {
                log.warn("Invalid channel ({}), can't configure port(s)", value);
                return;
            }
        }
    }

    // uses 'bandwidth' annotation to determine the channel spacing.
    private void updateOchPort(double bw, ConnectPoint srcCp, ConnectPoint dstCp) {
        Device src = deviceService.getDevice(srcCp.deviceId());
        Device dst = deviceService.getDevice(dstCp.deviceId());
        // bandwidth in MHz (assuming Hz - linc is not clear if that or Mb).
        Frequency spacing = Frequency.ofMHz(bw);
        // channel bandwidth is smaller than smallest standard channel spacing.
        ChannelSpacing chsp = null;
        if (spacing.compareTo(ChannelSpacing.CHL_6P25GHZ.frequency()) <= 0) {
            chsp = ChannelSpacing.CHL_6P25GHZ;
        }
        for (int i = 1; i < ChannelSpacing.values().length; i++) {
            Frequency val = ChannelSpacing.values()[i].frequency();
            // pick the next highest or equal channel interval.
            if (val.isLessThan(spacing)) {
                chsp = ChannelSpacing.values()[i - 1];
                break;
            }
        }
        if (chsp == null) {
            log.warn("Invalid channel spacing ({}), can't configure port(s)", spacing);
            return;
        }
        OchSignal signal = new OchSignal(GridType.DWDM, chsp, 1, 1);
        if (src.type() == Device.Type.ROADM) {
            PortDescription portDesc = ochPortDescription(srcCp.port(), true,
                    OduSignalType.ODU4, true, signal);
            descriptions.put(srcCp, portDesc);
            deviceProviderService.portStatusChanged(srcCp.deviceId(), portDesc);
        }
        if (dst.type() == Device.Type.ROADM) {
            PortDescription portDesc = ochPortDescription(dstCp.port(), true,
                    OduSignalType.ODU4, true, signal);
            descriptions.put(dstCp, portDesc);
            deviceProviderService.portStatusChanged(dstCp.deviceId(), portDesc);
        }
    }

    private void updateOmsPorts(int numChls, ConnectPoint srcCp, ConnectPoint dstCp) {
        // round down to largest slot that allows numChl channels to fit into C band range
        ChannelSpacing chl = null;
        Frequency perChl = TOTAL.floorDivision(numChls);
        for (int i = 0; i < ChannelSpacing.values().length; i++) {
            Frequency val = ChannelSpacing.values()[i].frequency();
            if (val.isLessThan(perChl)) {
                chl = ChannelSpacing.values()[i];
                break;
            }
        }
        if (chl == null) {
            chl = ChannelSpacing.CHL_6P25GHZ;
        }

        // if true, there was less channels than can be tightly packed.
        Frequency grid = chl.frequency();
        // say Linc's 1st slot starts at CENTER and goes up from there.
        Frequency min = Spectrum.CENTER_FREQUENCY.add(grid);
        Frequency max = Spectrum.CENTER_FREQUENCY.add(grid.multiply(numChls));

        PortDescription srcPortDesc = new OmsPortDescription(srcCp.port(), true, min, max, grid);
        PortDescription dstPortDesc = new OmsPortDescription(dstCp.port(), true, min, max, grid);
        descriptions.put(srcCp, srcPortDesc);
        descriptions.put(dstCp, dstPortDesc);
        deviceProviderService.portStatusChanged(srcCp.deviceId(), srcPortDesc);
        deviceProviderService.portStatusChanged(dstCp.deviceId(), dstPortDesc);
    }

    // Parses the given JSON and provides hosts as configured.
    private void parseHosts() {
        try {
            JsonNode nodes = cfg.get("hosts");
            if (nodes != null) {
                for (JsonNode node : nodes) {
                    parseHost(node);

                    // FIXME: hack to make sure host attributes take
                    // This will be fixed when GossipHostStore uses ECM
                    parseHost(node);
                }
            }
        } finally {
            hostProviderRegistry.unregister(this);
        }
    }

    // Parses the given node with host data and supplies the host.
    private void parseHost(JsonNode node) {
        MacAddress mac = MacAddress.valueOf(get(node, "mac"));
        VlanId vlanId = VlanId.vlanId((short) node.get("vlan").asInt(VlanId.UNTAGGED));
        HostId hostId = HostId.hostId(mac, vlanId);
        SparseAnnotations annotations = annotations(node.get("annotations"));
        HostLocation location = new HostLocation(connectPoint(get(node, "location")), 0);

        String[] ipStrings = get(node, "ip", "").split(",");
        Set<IpAddress> ips = new HashSet<>();
        for (String ip : ipStrings) {
            ips.add(IpAddress.valueOf(ip.trim()));
        }

        DefaultHostDescription desc =
                new DefaultHostDescription(mac, vlanId, location, ips, annotations);
        hostProviderService.hostDetected(hostId, desc, false);

        connectPoints.add(location);
    }

    // Adds any missing device ports for configured links and host locations.
    private void addMissingPorts() {
        deviceService.getDevices().forEach(this::addMissingPorts);
    }

    // Adds any missing device ports.
    private void addMissingPorts(Device device) {
        try {
            List<Port> ports = deviceService.getPorts(device.id());
            Set<ConnectPoint> existing = ports.stream()
                    .map(p -> new ConnectPoint(device.id(), p.number()))
                    .collect(Collectors.toSet());
            Set<ConnectPoint> missing = connectPoints.stream()
                    .filter(cp -> cp.deviceId().equals(device.id()))
                    .filter(cp -> !existing.contains(cp))
                    .collect(Collectors.toSet());

            if (!missing.isEmpty()) {
                List<PortDescription> newPorts = Stream.concat(
                        ports.stream().map(this::description),
                        missing.stream().map(this::description)
                ).collect(Collectors.toList());
                deviceProviderService.updatePorts(device.id(), newPorts);
            }
        } catch (IllegalArgumentException e) {
            log.warn("Error pushing ports: {}", e.getMessage());
        }
    }

    // Creates a port description from the specified port.
    private PortDescription description(Port p) {
        switch (p.type()) {
            case OMS:
                OmsPort op = (OmsPort) p;
                return new OmsPortDescription(
                        op.number(), op.isEnabled(), op.minFrequency(), op.maxFrequency(), op.grid());
            case OCH:
                OchPort ochp = (OchPort) p;
                return ochPortDescription(
                        ochp.number(), ochp.isEnabled(), ochp.signalType(), ochp.isTunable(), ochp.lambda());
            case ODUCLT:
                OduCltPort odup = (OduCltPort) p;
                return new OduCltPortDescription(
                        odup.number(), odup.isEnabled(), odup.signalType());
            default:
                return new DefaultPortDescription(p.number(), p.isEnabled(), p.type(), p.portSpeed());
        }
    }

    // Creates a port description from the specified connection point if none created earlier.
    private PortDescription description(ConnectPoint cp) {
        PortDescription saved = descriptions.get(cp);
        if (saved != null) {
            return saved;
        }
        Port p = deviceService.getPort(cp.deviceId(), cp.port());
        if (p == null) {
            return new DefaultPortDescription(cp.port(), true);
        }
        return description(p);
    }

    // Produces set of annotations from the given JSON node.
    private SparseAnnotations annotations(JsonNode node) {
        if (node == null) {
            return DefaultAnnotations.EMPTY;
        }

        DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
        Iterator<String> it = node.fieldNames();
        while (it.hasNext()) {
            String k = it.next();
            builder.set(k, node.get(k).asText());
        }
        return builder.build();
    }

    // Produces a connection point from the specified uri/port text.
    private ConnectPoint connectPoint(String text) {
        int i = text.lastIndexOf("/");
        String portName = text.substring(i + 1);
        DeviceId deviceId = deviceId(text.substring(0, i));

        for (Port port : deviceService.getPorts(deviceId)) {
            PortNumber pn = port.number();
            if (pn.name().equals(portName)) {
                return new ConnectPoint(deviceId, pn);
            }
        }

        long portNum;
        try {
            portNum = Long.parseLong(portName);
        } catch (NumberFormatException e) {
            portNum = 0;
        }

        return new ConnectPoint(deviceId, portNumber(portNum, portName));
    }

    // Returns string form of the named property in the given JSON object.
    private String get(JsonNode node, String name) {
        return node.path(name).asText();
    }

    // Returns string form of the named property in the given JSON object.
    private String get(JsonNode node, String name, String defaultValue) {
        return node.path(name).asText(defaultValue);
    }

    @Override
    public void roleChanged(DeviceId device, MastershipRole newRole) {
        deviceProviderService.receivedRoleReply(device, newRole, newRole);
    }

    @Override
    public void triggerProbe(DeviceId deviceId) {
    }

    @Override
    public void triggerProbe(Host host) {
    }

    @Override
    public void changePortState(DeviceId deviceId, PortNumber portNumber,
                                boolean enable) {
    }

    @Override
    public ProviderId id() {
        return PID;
    }

    @Override
    public boolean isReachable(DeviceId device) {
        return true;
    }

    /**
     * Prepares to count device added/available/removed events.
     *
     * @param count number of events to count
     */
    protected void prepareForDeviceEvents(int count) {
        deviceLatch = new CountDownLatch(count);
        deviceService.addListener(deviceEventCounter);
    }

    /**
     * Waits for all expected device added/available/removed events.
     */
    protected void waitForDeviceEvents() {
        try {
            deviceLatch.await(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.warn("Device events did not arrive in time");
        }
        deviceService.removeListener(deviceEventCounter);
    }

    // Counts down number of device added/available/removed events.
    private class DeviceEventCounter implements DeviceListener {
        @Override
        public void event(DeviceEvent event) {
            DeviceEvent.Type type = event.type();
            if (type == DEVICE_ADDED || type == DEVICE_AVAILABILITY_CHANGED) {
                deviceLatch.countDown();
            }
        }
    }



}
