/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 com.epam.dlab.automation.test;

import com.epam.dlab.automation.docker.AckStatus;
import com.epam.dlab.automation.docker.SSHConnect;
import com.epam.dlab.automation.helper.CloudHelper;
import com.epam.dlab.automation.helper.ConfigPropertyValue;
import com.epam.dlab.automation.helper.NamingHelper;
import com.epam.dlab.automation.helper.PropertiesResolver;
import com.jcraft.jsch.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.testng.Assert.*;

class TestDataEngineService {
    private final static Logger LOGGER = LogManager.getLogger(TestDataEngineService.class);
    
    private final static String COMMAND_COPY_TO_NOTEBOOK;
    private final static String COMMAND_RUN_PYTHON;
    private final static String COMMAND_RUN_PYTHON2;

    static {
        COMMAND_COPY_TO_NOTEBOOK = "scp -r -i %s -o 'StrictHostKeyChecking no' ~/%s %s@%s:/tmp/%s";
        COMMAND_RUN_PYTHON = CloudHelper.getPythonTestingScript();
        COMMAND_RUN_PYTHON2 = CloudHelper.getPythonTestingScript2();
    }


	void run(String notebookName, String notebookTemplate, String clusterName) throws Exception {
        Session ssnSession = null;
        try {
            LOGGER.info("{}: Copying test data copy scripts {} to SSN {}...",
            		notebookName, NamingHelper.getStorageName(), NamingHelper.getSsnIp());
            ssnSession = SSHConnect.getSession(ConfigPropertyValue.getClusterOsUser(), NamingHelper.getSsnIp(), 22);
            copyFileToSSN(ssnSession, PropertiesResolver.getNotebookTestDataCopyScriptLocation(), "");
			executePythonScript2(ssnSession, clusterName,
					new File(PropertiesResolver.getNotebookTestDataCopyScriptLocation()).getName(),
					notebookName, notebookTemplate);
        } finally {
            if (ssnSession != null && ssnSession.isConnected()) {
	            ssnSession.disconnect();
	        }
        }
    }
    
    //TODO refactor two methods and make one
	private void executePythonScript2(Session ssnSession, String clusterName, String notebookTestFile,
									  String notebookName, String notebookTemplate) throws JSchException,
			InterruptedException {
        String command;
        AckStatus status;

        command = String.format(COMMAND_RUN_PYTHON2, ConfigPropertyValue.getClusterOsUser(), notebookTestFile,
				NamingHelper.getStorageName(), notebookTemplate);
        LOGGER.info("{}: Executing command {}...", notebookName, command);

        ChannelExec runScript = SSHConnect.setCommand(ssnSession, command);
        status = SSHConnect.checkAck(runScript);
        LOGGER.info("{}: Script execution status message {} and code {}", notebookName, status.getMessage(), status.getStatus());
        assertTrue(status.isOk(), notebookName + ": The python script execution wasn`t successful on : " + clusterName);

        LOGGER.info("{}: Python script executed successfully ", notebookName);
    }

	private void executePythonScript(String Ip, String cluster_name, String notebookTestFile, int assignedPort,
									 String notebookName) throws JSchException, InterruptedException {
        String command;
        AckStatus status;
        Session session = SSHConnect.getForwardedConnect(ConfigPropertyValue.getClusterOsUser(), Ip, assignedPort);

        try {
            command = String.format(COMMAND_RUN_PYTHON,
                    "/tmp/" +  notebookTestFile,
                    NamingHelper.getStorageName(),
                    cluster_name,
                    ConfigPropertyValue.getClusterOsUser());
            LOGGER.info(String.format("{}: Executing command %s...", command), notebookName);

            ChannelExec runScript = SSHConnect.setCommand(session, command);
            status = SSHConnect.checkAck(runScript);
			LOGGER.info("{}: Script execution status message {} and status code {}", notebookName, status.getMessage(),
					status.getStatus());
            assertTrue(status.isOk(), notebookName + ": The python script execution wasn`t successful on " + cluster_name);

            LOGGER.info("{}: Python script executed successfully ", notebookName);
        }
        finally {
            if(session != null && session.isConnected()) {
                LOGGER.info("{}: Closing notebook session", notebookName);
                session.disconnect();
            }
        }
    }

	void run2(String ssnIP, String noteBookIp, String clusterName, File notebookScenarioDirectory,
			  File notebookTemplatesDirectory, String notebookName)
            throws JSchException, IOException, InterruptedException {
		LOGGER.info("Python tests for directories {} and {} will be started ...", notebookScenarioDirectory,
				notebookTemplatesDirectory);
    	if (ConfigPropertyValue.isRunModeLocal()) {
    		LOGGER.info("  tests are skipped");
    		return;
    	}

		assertTrue(notebookScenarioDirectory.exists(), notebookName + ": Checking notebook scenario directory " +
				notebookScenarioDirectory);
        assertTrue(notebookScenarioDirectory.isDirectory());

		assertTrue(notebookTemplatesDirectory.exists(), notebookName + ": Checking notebook templates directory " +
				notebookTemplatesDirectory);
        assertTrue(notebookTemplatesDirectory.isDirectory());

        String [] templatesFiles = notebookTemplatesDirectory.list();
        assertNotNull(templatesFiles, "Notebook " + notebookName + " templates directory is empty!");

    	String [] scenarioFiles = notebookScenarioDirectory.list();
        assertNotNull(scenarioFiles, "Notebook " + notebookName + " scenario directory is empty!");

		assertEquals(1, scenarioFiles.length, "The python script location " + notebookScenarioDirectory +
				" found more more then 1 file, expected 1 *.py file, but found multiple files: " +
				Arrays.toString(scenarioFiles));
        assertTrue(scenarioFiles[0].endsWith(".py"), "The python script was not found");
        // it is assumed there should be 1 python file.
        String notebookScenarioTestFile = scenarioFiles[0];

        Session ssnSession = SSHConnect.getSession(ConfigPropertyValue.getClusterOsUser(), ssnIP, 22);
        try {
            LOGGER.info("{}: Copying scenario test file to SSN {}...", notebookName, ssnIP);
			copyFileToSSN(ssnSession, Paths.get(notebookScenarioDirectory.getAbsolutePath(),
					notebookScenarioTestFile).toString(), "");

        	LOGGER.info("{}: Copying scenario test file to Notebook {}...", notebookName, noteBookIp);
            copyFileToNotebook(ssnSession, notebookScenarioTestFile, noteBookIp, "");

            LOGGER.info("In notebook templates directory {} available following template files: {}",
                    notebookTemplatesDirectory, Arrays.toString(templatesFiles));

            if(existsInSSN(ssnSession, NamingHelper.getNotebookTestTemplatesPath(notebookName))){
				LOGGER.info("{}: Corresponding folder for notebook templates already exists in SSN {} " +
						"and will be removed ...", notebookName, ssnIP);
                removeFromSSN(ssnSession, NamingHelper.getNotebookTestTemplatesPath(notebookName).split("/")[0]);
            }

            LOGGER.info("{}: Creating subfolder in home directory in SSN for copying templates {}...", notebookName, ssnIP);
            mkDirInSSN(ssnSession, NamingHelper.getNotebookTestTemplatesPath(notebookName));

            LOGGER.info("{}: Copying templates to SSN {}...", notebookName, ssnIP);
            for(String filename : templatesFiles){
                copyFileToSSN(ssnSession, Paths.get(notebookTemplatesDirectory.getAbsolutePath(), filename).toString(),
                        NamingHelper.getNotebookTestTemplatesPath(notebookName));
            }

            LOGGER.info("{}: Copying templates to Notebook {}...", notebookName, noteBookIp);
            copyFileToNotebook(ssnSession, NamingHelper.getNotebookTestTemplatesPath(notebookName),
                        noteBookIp, notebookName);

			if (!clusterName.equalsIgnoreCase(NamingHelper.CLUSTER_ABSENT)
					|| !NamingHelper.isClusterRequired(notebookName)) {
				LOGGER.info("{}: Port forwarding from ssn {} to notebook {}...", notebookName, ssnIP, noteBookIp);
				int assignedPort = ssnSession.setPortForwardingL(0, noteBookIp, 22);
				LOGGER.info("{}: Port forwarded localhost:{} -> {}:22", notebookName, assignedPort, noteBookIp);
				executePythonScript(noteBookIp, clusterName, notebookScenarioTestFile, assignedPort, notebookName);
			}
        }
        finally {
            if(ssnSession != null && ssnSession.isConnected()) {
                LOGGER.info("{}: Closing ssn session", notebookName);
                ssnSession.disconnect();
            }
        }
    }

    // Copies file to subfolder of home directory of SSN. If parameter 'destDirectoryInSSN' is empty string then copies
    // to home directory.
	private void copyFileToSSN(Session ssnSession, String sourceFilenameWithPath, String destDirectoryInSSN)
			throws IOException, JSchException {
        LOGGER.info("Copying {} to SSN...", sourceFilenameWithPath);
        File file = new File(sourceFilenameWithPath);
        assertTrue(file.exists(), "Source file " + sourceFilenameWithPath + " doesn't exist!");
        LOGGER.info("Source file {} exists: {}", sourceFilenameWithPath, file.exists());

        ChannelSftp channelSftp = null;
        FileInputStream src = new FileInputStream(file);
        try {
        	channelSftp = SSHConnect.getChannelSftp(ssnSession);
			channelSftp.put(src,
					String.format("/home/%s/%s%s", ConfigPropertyValue.getClusterOsUser(), destDirectoryInSSN, file
							.getName()));
        } catch (SftpException e) {
            LOGGER.error("An error occured during copying file to SSN: {}", e);
			fail("Copying file " + file.getName() + " to SSN is failed");
        } finally {
            if(channelSftp != null && channelSftp.isConnected()) {
                channelSftp.disconnect();
            }
        }

    }

    // Creates a folder in home directory of SSN
    private void mkDirInSSN(Session ssnSession, String directoryName) throws JSchException {
        String newDirectoryAbsolutePath = String.format("/home/%s/%s", ConfigPropertyValue.getClusterOsUser(), directoryName);
        LOGGER.info("Creating directory {} in SSN...", newDirectoryAbsolutePath);

        ChannelSftp channelSftp = null;
        try {
            channelSftp = SSHConnect.getChannelSftp(ssnSession);
            if(!directoryName.equals("")){
                String[] partsOfPath = directoryName.split("/");
                StringBuilder sb = new StringBuilder();
                for(String partOfPath : partsOfPath){
                    if(partOfPath.equals("")){
                        continue;
                    }
                    sb.append(partOfPath);
                    if(!existsInSSN(ssnSession, sb.toString())){
                        LOGGER.info("Creating directory {} in SSN...",
                                String.format("/home/%s/%s", ConfigPropertyValue.getClusterOsUser(), sb.toString()));
                        channelSftp.mkdir(String.format("/home/%s/%s", ConfigPropertyValue.getClusterOsUser(), sb.toString()));
                    }
                    sb.append("/");
                }
            }
            assertTrue(channelSftp.stat(newDirectoryAbsolutePath).isDir(), "Directory " + newDirectoryAbsolutePath +
                    " wasn't created in SSN!");
        } catch (SftpException e) {
            LOGGER.error("An error occured during creation directory in SSN: {}", e);
			fail("Creating directory " + newDirectoryAbsolutePath + " in SSN is failed");
        } finally {
            if(channelSftp != null && channelSftp.isConnected()) {
                channelSftp.disconnect();
            }
        }

    }

    // Checks if file exists in home directory of SSN
    private boolean existsInSSN(Session ssnSession, String fileName) throws JSchException {
        String homeDirectoryAbsolutePath = String.format("/home/%s", ConfigPropertyValue.getClusterOsUser());
        LOGGER.info("Checking if file/directory {} exists in home directory {} of SSN...", fileName, homeDirectoryAbsolutePath);

        boolean isFileEmbeddedIntoFolder = fileName.contains("/");
        ChannelSftp channelSftp = null;
        List<String> fileNames = new ArrayList<>();
        try {
            channelSftp = SSHConnect.getChannelSftp(ssnSession);
            Vector fileDataList = channelSftp.ls(homeDirectoryAbsolutePath);
            for (Object fileData : fileDataList) {
                ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) fileData;
                fileNames.add(entry.getFilename());
            }
            if(fileNames.isEmpty()){
				LOGGER.info("Does file/directory {} exist in home directory {} of SSN: {}",
                        fileName, homeDirectoryAbsolutePath, "false");
                return false;
            }
            LOGGER.info("In home directory {} of SSN there are following files: {}",
                    homeDirectoryAbsolutePath, fileNames);
            if(!isFileEmbeddedIntoFolder){
				LOGGER.info("Does file/directory {} exist in home directory {} of SSN: {}",
                        fileName, homeDirectoryAbsolutePath, fileNames.contains(fileName));
                return fileNames.contains(fileName);
            }else{
                List<String> partsOfPath =
                        Stream.of(fileName.split("/")).filter(e -> !e.equals("")).collect(Collectors.toList());
                StringBuilder currentPath = new StringBuilder(homeDirectoryAbsolutePath);
                for(int i = 0; i < partsOfPath.size(); i++){
                    String partOfPath = partsOfPath.get(i);
                    if(fileNames.isEmpty() || !fileNames.contains(partOfPath)){
						LOGGER.info("Does file/directory {} exist in home directory {} of SSN: {}",
                                fileName, homeDirectoryAbsolutePath, "false");
                        return false;
                    }else{
                        if(i == partsOfPath.size() - 1){
							LOGGER.info("Does file/directory {} exist in home directory {} of SSN: {}",
                                    fileName, homeDirectoryAbsolutePath, "true");
                            return true;
                        }
                        currentPath.append("/").append(partOfPath);
                        fileDataList = channelSftp.ls(currentPath.toString());
                        fileNames = new ArrayList<>();
                        for (Object fileData : fileDataList) {
                            ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) fileData;
                            fileNames.add(entry.getFilename());
                        }

                    }

                }

            }

        } catch (SftpException e) {
            LOGGER.error("An error occured during obtaining list of files from home directory in SSN: {}", e);
        } finally {
            if(channelSftp != null && channelSftp.isConnected()) {
                channelSftp.disconnect();
            }
        }
		LOGGER.info("Does file/directory {} exist in home directory {} of SSN: {}",
                fileName, homeDirectoryAbsolutePath, "false");
        return false;
    }

    // Removes file or directory from home directory of SSN
    private void removeFromSSN(Session ssnSession, String fileNameWithRelativePath) throws JSchException {
        String absoluteFilePath = String.format("/home/%s/%s", ConfigPropertyValue.getClusterOsUser(), fileNameWithRelativePath);

        ChannelSftp channelSftp = null;
        try {
            channelSftp = SSHConnect.getChannelSftp(ssnSession);
            boolean isDir = channelSftp.stat(absoluteFilePath).isDir();
            LOGGER.info("Is file {} a directory in SSN: {}", absoluteFilePath, isDir);
            if(isDir){
                LOGGER.info("Removing directory {} from SSN...", absoluteFilePath);
                recursiveDirectoryDelete(ssnSession, absoluteFilePath);
            }else{
                LOGGER.info("Removing file {} from SSN...", absoluteFilePath);
                channelSftp.rm(absoluteFilePath);
            }
        } catch (SftpException e) {
            LOGGER.error("An error occured during removing file {} from SSN: {}", absoluteFilePath, e);
        } finally {
            if(channelSftp != null && channelSftp.isConnected()) {
                channelSftp.disconnect();
            }
        }
    }

    private void recursiveDirectoryDelete(Session ssnSession, String remoteDir) throws JSchException{
        ChannelSftp channelSftp = null;
        try{
            channelSftp = SSHConnect.getChannelSftp(ssnSession);
            boolean isDir = channelSftp.stat(remoteDir).isDir();
            if(isDir){
                Vector dirList = channelSftp.ls(remoteDir);
                for(Object fileData : dirList){
                    ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) fileData;
                    if(!(entry.getFilename().equals(".") || entry.getFilename().equals(".."))){
                        if(entry.getAttrs().isDir()){
                            recursiveDirectoryDelete(ssnSession, remoteDir + File.separator
                                    + entry.getFilename() + File.separator);
                        }
                        else{
                            channelSftp.rm(remoteDir + entry.getFilename());
                        }
                    }
                }
                channelSftp.cd("..");
                channelSftp.rmdir(remoteDir);
            }
        }
        catch (SftpException e){
            LOGGER.error("An error occured while deleting directory {}: {}", remoteDir, e.getMessage());
        }
        finally {
            if(channelSftp != null && channelSftp.isConnected()) {
                channelSftp.disconnect();
            }
        }
    }

	private void copyFileToNotebook(Session session, String filename, String ip, String notebookName)
			throws JSchException, InterruptedException {
    	String command = String.format(COMMAND_COPY_TO_NOTEBOOK,
    			"keys/"+ Paths.get(ConfigPropertyValue.getAccessKeyPrivFileName()).getFileName().toString(),
                filename,
                ConfigPropertyValue.getClusterOsUser(),
                ip,
                NamingHelper.getNotebookType(notebookName));

    	LOGGER.info("Copying {} to notebook...", filename);
    	LOGGER.info("  Run command: {}", command);

        ChannelExec copyResult = SSHConnect.setCommand(session, command);
        AckStatus status = SSHConnect.checkAck(copyResult);

        LOGGER.info("Copied {}: {}", filename, status.toString());
        assertTrue(status.isOk());
    }

}
