/*
 * Copyright 2016 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.cordvtn;

import com.google.common.collect.Sets;
import com.google.common.io.CharStreams;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * {@code RemoteIpCommandUtil} provides methods to help execute Linux IP commands to a remote server.
 * It opens individual exec channels for each command. User can create a session with {@code connect}
 * method and then execute a series commands. After done with all commands, the session must be closed
 * explicitly by calling {@code disconnect}.
 */
public final class RemoteIpCommandUtil {

    protected static final Logger log = getLogger(RemoteIpCommandUtil.class);

    private static final String STRICT_HOST_CHECKING = "StrictHostKeyChecking";
    private static final String DEFAULT_STRICT_HOST_CHECKING = "no";
    private static final int DEFAULT_SESSION_TIMEOUT = 60000; // milliseconds

    private static final String IP_PATTERN = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.)" +
            "{3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))$";

    private static final String IP_ADDR_SHOW = "sudo ip addr show %s";
    private static final String IP_ADDR_FLUSH = "sudo ip addr flush %s";
    private static final String IP_ADDR_ADD = "sudo ip addr add %s dev %s";
    private static final String IP_ADDR_DELETE = "sudo ip addr delete %s dev %s";
    private static final String IP_LINK_SHOW = "sudo ip link show %s";
    private static final String IP_LINK_UP = "sudo ip link set %s up";

    /**
     * Default constructor.
     */
    private RemoteIpCommandUtil() {
    }

    /**
     * Adds a given IP address to a given device.
     *
     * @param session ssh connection
     * @param ip ip address
     * @param device device name to assign the ip address
     * @return true if the command succeeds, or false
     */
    public static boolean addIp(Session session, IpPrefix ip, String device) {
        if (session == null || !session.isConnected()) {
            return false;
        }

        executeCommand(session, String.format(IP_ADDR_ADD, ip, device));
        Set<IpPrefix> result = getCurrentIps(session, device);
        return result.contains(ip);
    }

    /**
     * Removes the IP address from a given device.
     *
     * @param session ssh connection
     * @param ip ip address
     * @param device device name
     * @return true if the command succeeds, or false
     */
    public static boolean deleteIp(Session session, IpPrefix ip, String device) {
        if (session == null || !session.isConnected()) {
            return false;
        }

        executeCommand(session, String.format(IP_ADDR_DELETE, ip, device));
        Set<IpPrefix> result = getCurrentIps(session, device);
        return !result.contains(ip);
    }

    /**
     * Removes all IP address on a given device.
     *
     * @param session ssh connection
     * @param device device name
     * @return true if the command succeeds, or false
     */
    public static boolean flushIp(Session session, String device) {
        if (session == null || !session.isConnected()) {
            return false;
        }

        executeCommand(session, String.format(IP_ADDR_FLUSH, device));
        return getCurrentIps(session, device).isEmpty();
    }

    /**
     * Returns a set of IP address that a given device has.
     *
     * @param session ssh connection
     * @param device device name
     * @return set of IP prefix or empty set
     */
    public static Set<IpPrefix> getCurrentIps(Session session, String device) {
        if (session == null || !session.isConnected()) {
            return Sets.newHashSet();
        }

        String output = executeCommand(session, String.format(IP_ADDR_SHOW, device));
        Set<IpPrefix> result = Pattern.compile(" ")
                .splitAsStream(output)
                .filter(s -> s.matches(IP_PATTERN))
                .map(IpPrefix::valueOf)
                .collect(Collectors.toSet());

        return result;
    }

    /**
     * Sets link state up for a given device.
     *
     * @param session ssh connection
     * @param device device name
     * @return true if the command succeeds, or false
     */
    public static boolean setInterfaceUp(Session session, String device) {
        if (session == null || !session.isConnected()) {
            return false;
        }

        executeCommand(session, String.format(IP_LINK_UP, device));
        return isInterfaceUp(session, device);
    }

    /**
     * Checks if a given interface is up or not.
     *
     * @param session ssh connection
     * @param device device name
     * @return true if the interface is up, or false
     */
    public static boolean isInterfaceUp(Session session, String device) {
        if (session == null || !session.isConnected()) {
            return false;
        }

        String output = executeCommand(session, String.format(IP_LINK_SHOW, device));
        return output != null && output.contains("UP");
    }

    /**
     * Creates a new session with a given access information.
     *
     * @param sshInfo information to ssh to the remove server
     * @return ssh session, or null
     */
    public static Session connect(SshAccessInfo sshInfo) {
        try {
            JSch jsch = new JSch();
            jsch.addIdentity(sshInfo.privateKey());

            Session session = jsch.getSession(sshInfo.user(),
                                      sshInfo.remoteIp().toString(),
                                      sshInfo.port().toInt());
            session.setConfig(STRICT_HOST_CHECKING, DEFAULT_STRICT_HOST_CHECKING);
            session.connect(DEFAULT_SESSION_TIMEOUT);

            return session;
        } catch (JSchException e) {
            log.debug("Failed to connect to {} due to {}", sshInfo.toString(), e.toString());
            return null;
        }
    }

    /**
     * Closes a connection.
     *
     * @param session session
     */
    public static void disconnect(Session session) {
        if (session.isConnected()) {
            session.disconnect();
        }
    }

    /**
     * Executes a given command. It opens exec channel for the command and closes
     * the channel when it's done.
     *
     * @param session ssh connection to a remote server
     * @param command command to execute
     * @return command output string if the command succeeds, or null
     */
    private static String executeCommand(Session session, String command) {
        if (session == null || !session.isConnected()) {
            return null;
        }

        log.debug("Execute command {} to {}", command, session.getHost());

        try {
            Channel channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);
            channel.setInputStream(null);
            InputStream output = channel.getInputStream();

            channel.connect();
            String result = CharStreams.toString(new InputStreamReader(output));
            channel.disconnect();

            return result;
        } catch (JSchException | IOException e) {
            log.debug("Failed to execute command {} due to {}", command, e.toString());
            return null;
        }
    }
}
