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

import com.google.common.annotations.Beta;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
 * NETCONF session object that allows NETCONF operations on top with the physical
 * device on top of an SSH connection.
 */
// TODO change return type of methods to <Capability, XMLdoc, string or yang obj>
public interface NetconfSession {

    /**
     * Executes an asynchronous RPC to the server and obtains a future to be completed.
     *
     * The caller must ensure that the message-id in any request is unique
     * for the session
     *
     * @deprecated  - 1.10.0 do not remove needs reworking
     * @param request the XML containing the RPC for the server.
     * @return Server response or ERROR
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    @Deprecated
    CompletableFuture<String> request(String request) throws NetconfException;

    /**
     * Executes an asynchronous RPC request to the server and obtains a future
     * for it's response.
     *
     * @param request the XML containing the RPC request for the server.
     * @return Server response or ERROR
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     * @throws NetconfTransportException on secure transport-layer error
     */
    default CompletableFuture<String> rpc(String request) throws NetconfException {
        return request(request);
    }

    /**
     * Retrieves the specified configuration.
     *
     * @param datastore to retrieve configuration from
     * @return specified configuration
     *
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    default CompletableFuture<CharSequence> asyncGetConfig(DatastoreId datastore) throws NetconfException {
        StringBuilder rpc = new StringBuilder();
        rpc.append("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n");
        rpc.append("<get-config>\n");
        rpc.append("<source>\n");
        rpc.append('<').append(checkNotNull(datastore)).append("/>");
        rpc.append("</source>");
        // filter here
        rpc.append("</get-config>\n");
        rpc.append("</rpc>");

        return rpc(rpc.toString())
                .thenApply(msg -> {
                    // crude way of removing rpc-reply envelope
                    int begin = msg.indexOf("<data>");
                    int end = msg.lastIndexOf("</data>");
                    if (begin != -1 && end != -1) {
                        return msg.subSequence(begin, end + "</data>".length());
                    } else {
                        // FIXME probably should exceptionally fail here.
                        return msg;
                    }
                });
    }

    /**
     * Retrieves running configuration and device state.
     *
     * @return running configuration and device state
     *
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    default CompletableFuture<CharSequence> asyncGet() throws NetconfException {
        StringBuilder rpc = new StringBuilder();
        rpc.append("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n");
        rpc.append("<get>\n");
        // filter here
        rpc.append("</get>\n");
        rpc.append("</rpc>");
        return rpc(rpc.toString())
                .thenApply(msg -> {
                    // crude way of removing rpc-reply envelope
                    int begin = msg.indexOf("<data>");
                    int end = msg.lastIndexOf("</data>");
                    if (begin != -1 && end != -1) {
                        return msg.subSequence(begin, end + "</data>".length());
                    } else {
                        // FIXME probably should exceptionally fail here.
                        return msg;
                    }
                });

    }


    /**
     * Retrieves the requested configuration, different from get-config.
     *
     * @param request the XML containing the request to the server.
     * @return device running configuration
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    String get(String request) throws NetconfException;

    /**
     * Retrieves the requested data.
     *
     * @param filterSchema XML subtrees to include in the reply
     * @param withDefaultsMode with-defaults mode
     * @return Server response
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    String get(String filterSchema, String withDefaultsMode)
            throws NetconfException;

    /**
     * Executes an synchronous RPC to the server and wrap the request in RPC header.
     *
     * @param request the XML containing the request to the server.
     * @return Server response or ERROR
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    String doWrappedRpc(String request) throws NetconfException;

    /**
     * Executes an synchronous RPC to the server.
     *
     * @param request the XML containing the RPC for the server.
     * @return Server response or ERROR
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    String requestSync(String request) throws NetconfException;

    /**
     * Retrieves the specified configuration.
     *
     * @param netconfTargetConfig the type of configuration to retrieve.
     * @return specified configuration.
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     *
     * @deprecated in 1.13.0 use async version instead.
     */
    @Deprecated
    String getConfig(DatastoreId netconfTargetConfig) throws NetconfException;

    /**
     * Retrieves part of the specified configuration based on the filterSchema.
     *
     * @param netconfTargetConfig       the type of configuration to retrieve.
     * @param configurationFilterSchema XML schema to filter the configuration
     *                                  elements we are interested in
     * @return device running configuration.
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    String getConfig(DatastoreId netconfTargetConfig,
                             String configurationFilterSchema)
            throws NetconfException;

    /**
     * Retrieves part of the specified configuration based on the filterSchema.
     *
     * @param newConfiguration configuration to set
     * @return true if the configuration was edited correctly
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    boolean editConfig(String newConfiguration) throws NetconfException;

    /**
     * Retrieves part of the specified configuration based on the filterSchema.
     *
     * @param netconfTargetConfig the targetConfiguration to change
     * @param mode                default-operation mode
     * @param newConfiguration    configuration to set
     * @return true if the configuration was edited correctly
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    boolean editConfig(DatastoreId netconfTargetConfig, String mode, String newConfiguration)
            throws NetconfException;

    /**
     * Copies the configuration between configuration datastores.
     * <p>
     * The target configuration can't be the running one
     *
     * @param destination configuration datastore
     * @param source configuration datastore
     * @return true if the configuration was copied correctly
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    boolean copyConfig(DatastoreId destination, DatastoreId source)
            throws NetconfException;

    /**
     * Copies the new configuration, an Url or a complete configuration xml tree
     * to the target configuration.
     * The target configuration can't be the running one
     *
     * @param netconfTargetConfig the type of configuration to retrieve.
     * @param newConfiguration configuration XML to set or URL tag to the configuration
     * @return true if the configuration was copied correctly
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
     boolean copyConfig(DatastoreId netconfTargetConfig, String newConfiguration)
            throws NetconfException;

    /**
     * Copies the new configuration, an Url or a complete configuration xml tree
     * to the target configuration.
     * The target configuration can't be the running one
     *
     * @param netconfTargetConfig the type of configuration to retrieve.
     * @param newConfiguration    configuration to set
     * @return true if the configuration was copied correctly
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    boolean copyConfig(String netconfTargetConfig, String newConfiguration)
            throws NetconfException;

    /**
     * Deletes part of the specified configuration based on the filterSchema.
     *
     * @param netconfTargetConfig the name of the configuration to delete
     * @return true if the configuration was copied correctly
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    boolean deleteConfig(DatastoreId netconfTargetConfig) throws NetconfException;

    /**
     * Starts subscription to the device's notifications.
     *
     * @throws NetconfException when there is a problem starting the subscription
     */
    void startSubscription() throws NetconfException;

    /**
     * Starts subscription to the device's notifications.
     *
     * @param filterSchema XML subtrees to indicate specific notification
     * @throws NetconfException when there is a problem starting the subscription
     */
    @Beta
    void startSubscription(String filterSchema) throws NetconfException;

    /**
     * Ends subscription to the device's notifications.
     *
     * @throws NetconfException when there is a problem ending the subscription
     */
    void endSubscription() throws NetconfException;

    /**
     * Locks the specified configuration.
     *
     * @param datastore configuration datastore to be locked
     * @return true if successful.
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    boolean lock(DatastoreId datastore) throws NetconfException;

    /**
     * Unlocks the specified configuration.
     *
     * @param datastore configuration datastore to be unlocked
     * @return true if successful.
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    boolean unlock(DatastoreId datastore) throws NetconfException;

    /**
     * Locks the running configuration.
     *
     * @return true if successful.
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    default boolean lock() throws NetconfException {
        return lock(DatastoreId.RUNNING);
    }

    /**
     * Unlocks the running configuration.
     *
     * @return true if successful.
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    default boolean unlock() throws NetconfException {
        return unlock(DatastoreId.RUNNING);
    }

    /**
     * Closes the Netconf session with the device.
     * the first time it tries gracefully, then kills it forcefully
     *
     * @return true if closed
     * @throws NetconfException when there is a problem in the communication process on
     * the underlying connection
     */
    boolean close() throws NetconfException;

    /**
     * Gets the session ID of the Netconf session.
     *
     * @return Session ID as a string.
     */
    String getSessionId();

    /**
     * Gets the capabilities of the remote Netconf device associated to this
     * session.
     *
     * @return Network capabilities as strings in a Set.
     *
     * @since 1.10.0
     */
    Set<String> getDeviceCapabilitiesSet();

    /**
     * Checks the state of the underlying SSH session and connection
     * and if necessary it reestablishes it.
     * Should be implemented, providing a default here for retrocompatibility.
     * @throws NetconfException when there is a problem in reestablishing
     * the connection or the session to the device.
     */
    default void checkAndReestablish() throws NetconfException {
        Logger log = LoggerFactory.getLogger(NetconfSession.class);
        log.error("Not implemented/exposed by the underlying session implementation");
    }

    /**
     * Sets the ONOS side capabilities.
     *
     * @param capabilities list of capabilities ONOS has.
     *
     * @since 1.10.0
     */
    default void setOnosCapabilities(Iterable<String> capabilities) {
        // default implementation should be removed in the future
        // no-op
    }

    /**
     * Remove a listener from the underlying stream handler implementation.
     *
     * @param listener event listener.
     */
    void addDeviceOutputListener(NetconfDeviceOutputEventListener listener);

    /**
     * Remove a listener from the underlying stream handler implementation.
     *
     * @param listener event listener.
     */
    void removeDeviceOutputListener(NetconfDeviceOutputEventListener listener);

    /**
     * Read the connect timeout that this session was created with.
     * @return timeout in seconds
     */
    default int timeoutConnectSec() {
        return 0;
    };

    /**
     * Read the reply timeout that this session was created with.
     * @return timeout in seconds
     */
    default int timeoutReplySec() {
        return 0;
    };

    /**
     * Read the idle timeout that this session was created with.
     * @return timeout in seconds
     */
    default int timeoutIdleSec() {
        return 0;
    };

}
