/*
 * 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.
 */

package org.onosproject.drivers.gnmi;

import io.grpc.StatusRuntimeException;
import org.onosproject.gnmi.api.GnmiClient;
import org.onosproject.gnmi.api.GnmiClientKey;
import org.onosproject.gnmi.api.GnmiController;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Abstract implementation of a behaviour handler for a gNMI device.
 */
public class AbstractGnmiHandlerBehaviour extends AbstractHandlerBehaviour {

    // Default timeout in seconds for device operations.
    private static final String DEVICE_REQ_TIMEOUT = "deviceRequestTimeout";
    private static final int DEFAULT_DEVICE_REQ_TIMEOUT = 60;

    public static final String GNMI_SERVER_ADDR_KEY = "gnmi_ip";
    public static final String GNMI_SERVER_PORT_KEY = "gnmi_port";
    private static final String GNMI_SERVICE_NAME = "gnmi";

    protected final Logger log = LoggerFactory.getLogger(getClass());
    protected DeviceId deviceId;
    protected DeviceService deviceService;
    protected Device device;
    protected GnmiController controller;
    protected GnmiClient client;

    protected boolean setupBehaviour() {
        deviceId = handler().data().deviceId();

        controller = handler().get(GnmiController.class);
        client = controller.getClient(deviceId);

        if (client == null) {
            log.warn("Unable to find client for {}, aborting operation", deviceId);
            return false;
        }

        return true;
    }

    protected GnmiClient createClient() {
        deviceId = handler().data().deviceId();
        controller = handler().get(GnmiController.class);

        final String serverAddr = this.data().value(GNMI_SERVER_ADDR_KEY);
        final String serverPortString = this.data().value(GNMI_SERVER_PORT_KEY);

        if (serverAddr == null || serverPortString == null) {
            log.warn("Unable to create client for {}, missing driver data key (required is {}, {}, and {})",
                    deviceId, GNMI_SERVER_ADDR_KEY, GNMI_SERVER_PORT_KEY);
            return null;
        }

        final int serverPort;
        try {
            serverPort = Integer.parseUnsignedInt(serverPortString);
        } catch (NumberFormatException e) {
            log.error("{} is not a valid gNMI port number", serverPortString);
            return null;
        }
        GnmiClientKey clientKey =
                new GnmiClientKey(GNMI_SERVICE_NAME, deviceId, serverAddr, serverPort);
        if (!controller.createClient(clientKey)) {
            log.warn("Unable to create client for {}, aborting operation", deviceId);
            return null;
        }
        return controller.getClient(deviceId);
    }

    /**
     * Returns the device request timeout driver property, or a default value
     * if the property is not present or cannot be parsed.
     *
     * @return timeout value
     */
    private int getDeviceRequestTimeout() {
        final String timeout = handler().driver()
                .getProperty(DEVICE_REQ_TIMEOUT);
        if (timeout == null) {
            return DEFAULT_DEVICE_REQ_TIMEOUT;
        } else {
            try {
                return Integer.parseInt(timeout);
            } catch (NumberFormatException e) {
                log.error("{} driver property '{}' is not a number, using default value {}",
                        DEVICE_REQ_TIMEOUT, timeout, DEFAULT_DEVICE_REQ_TIMEOUT);
                return DEFAULT_DEVICE_REQ_TIMEOUT;
            }
        }
    }

    /**
     * Convenience method to get the result of a completable future while
     * setting a timeout and checking for exceptions.
     *
     * @param future        completable future
     * @param opDescription operation description to use in log messages. Should
     *                      be a sentence starting with a verb ending in -ing,
     *                      e.g. "reading...", "writing...", etc.
     * @param defaultValue  value to return if operation fails
     * @param <U>           type of returned value
     * @return future result or default value
     */
    <U> U getFutureWithDeadline(CompletableFuture<U> future, String opDescription,
                                U defaultValue) {
        try {
            return future.get(getDeviceRequestTimeout(), TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("Exception while {} on {}", opDescription, deviceId);
        } catch (ExecutionException e) {
            final Throwable cause = e.getCause();
            if (cause instanceof StatusRuntimeException) {
                final StatusRuntimeException grpcError = (StatusRuntimeException) cause;
                log.warn("Error while {} on {}: {}", opDescription, deviceId, grpcError.getMessage());
            } else {
                log.error("Exception while {} on {}", opDescription, deviceId, e.getCause());
            }
        } catch (TimeoutException e) {
            log.error("Operation TIMEOUT while {} on {}", opDescription, deviceId);
        }
        return defaultValue;
    }
}
