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

package org.onosproject.drivers.gnmi;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import gnmi.Gnmi;
import gnmi.Gnmi.GetRequest;
import gnmi.Gnmi.GetResponse;
import org.onlab.packet.ChassisId;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.PortDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import static gnmi.Gnmi.Path;
import static gnmi.Gnmi.PathElem;
import static gnmi.Gnmi.Update;

/**
 * Class that discovers the device description and ports of a device that
 * supports the gNMI protocol and Openconfig models.
 */
public class OpenConfigGnmiDeviceDescriptionDiscovery
        extends AbstractGnmiHandlerBehaviour
        implements DeviceDescriptionDiscovery {

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

    private static final String LAST_CHANGE = "last-changed";

    private static final String UNKNOWN = "unknown";

    @Override
    public DeviceDescription discoverDeviceDetails() {
        return new DefaultDeviceDescription(
                data().deviceId().uri(),
                Device.Type.SWITCH,
                data().driver().manufacturer(),
                data().driver().hwVersion(),
                data().driver().swVersion(),
                UNKNOWN,
                new ChassisId(),
                true,
                DefaultAnnotations.builder()
                        .set(AnnotationKeys.PROTOCOL, "gNMI")
                        .build());
    }

    @Override
    public List<PortDescription> discoverPortDetails() {
        if (!setupBehaviour()) {
            return Collections.emptyList();
        }
        log.debug("Discovering port details on device {}", handler().data().deviceId());

        final GetResponse response = Futures.getUnchecked(client.get(buildPortStateRequest()));

        final Map<String, DefaultPortDescription.Builder> ports = Maps.newHashMap();
        final Map<String, DefaultAnnotations.Builder> annotations = Maps.newHashMap();

        // Creates port descriptions with port name and port number
        response.getNotificationList()
                .forEach(notification -> {
                    long timestamp = notification.getTimestamp();
                    notification.getUpdateList().forEach(update -> {
                        // /interfaces/interface[name=ifName]/state/...
                        final String ifName = update.getPath().getElem(1)
                                .getKeyMap().get("name");
                        if (!ports.containsKey(ifName)) {
                            ports.put(ifName, DefaultPortDescription.builder());
                            annotations.put(ifName, DefaultAnnotations.builder());
                        }
                        final DefaultPortDescription.Builder builder = ports.get(ifName);
                        final DefaultAnnotations.Builder annotationsBuilder = annotations.get(ifName);
                        parseInterfaceInfo(update, ifName, builder, annotationsBuilder, timestamp);
                    });
                });

        final List<PortDescription> portDescriptionList = Lists.newArrayList();
        ports.forEach((key, value) -> {
            DefaultAnnotations annotation = annotations.get(key).build();
            portDescriptionList.add(value.annotations(annotation).build());
        });
        return portDescriptionList;
    }

    private GetRequest buildPortStateRequest() {
        Path path = Path.newBuilder()
                .addElem(PathElem.newBuilder().setName("interfaces").build())
                .addElem(PathElem.newBuilder().setName("interface").putKey("name", "...").build())
                .addElem(PathElem.newBuilder().setName("state").build())
                .build();
        return GetRequest.newBuilder()
                .addPath(path)
                .setType(GetRequest.DataType.ALL)
                .setEncoding(Gnmi.Encoding.PROTO)
                .build();
    }

    /**
     * Parses the interface information.
     *
     * @param update the update received
     */
    private void parseInterfaceInfo(Update update,
                                    String ifName,
                                    DefaultPortDescription.Builder builder,
                                    DefaultAnnotations.Builder annotationsBuilder,
                                    long timestamp) {


        final Path path = update.getPath();
        final List<PathElem> elems = path.getElemList();
        final Gnmi.TypedValue val = update.getVal();
        if (elems.size() == 4) {
            // /interfaces/interface/state/ifindex
            // /interfaces/interface/state/oper-status
            final String pathElemName = elems.get(3).getName();
            switch (pathElemName) {
                case "ifindex": // port number
                    builder.withPortNumber(PortNumber.portNumber(val.getUintVal(), ifName));
                    return;
                case "oper-status":
                    builder.isEnabled(parseOperStatus(val.getStringVal()));
                    annotationsBuilder.set(LAST_CHANGE, String.valueOf(timestamp));
                    return;
                default:
                    break;
            }
        } else if (elems.size() == 5) {
            // /interfaces/interface/ethernet/config/port-speed
            final String pathElemName = elems.get(4).getName();
            if (pathElemName.equals("port-speed")) {
                builder.portSpeed(parsePortSpeed(val.getStringVal()));
                return;
            }
        }
        log.debug("Unknown path when parsing interface info: {}", path);
    }

    private boolean parseOperStatus(String operStatus) {
        switch (operStatus) {
            case "UP":
                return true;
            case "DOWN":
            default:
                return false;
        }
    }

    private long parsePortSpeed(String speed) {
        log.debug("Speed from config {}", speed);
        switch (speed) {
            case "SPEED_10MB":
                return 10;
            case "SPEED_100MB":
                return 100;
            case "SPEED_1GB":
                return 1000;
            case "SPEED_10GB":
                return 10000;
            case "SPEED_25GB":
                return 25000;
            case "SPEED_40GB":
                return 40000;
            case "SPEED_50GB":
                return 50000;
            case "SPEED_100GB":
                return 100000;
            default:
                log.warn("Unrecognized port speed string '{}'", speed);
                return 1000;
        }
    }
}
