/**
 * (c) Copyright IBM Corporation 2015.
 * (c) Copyright HCL Technologies Ltd. 2018. All Rights Reserved.
 * This is licensed under the following license.
 * The Eclipse Public 1.0 License (http://www.eclipse.org/legal/epl-v10.html)
 * U.S. Government Users Restricted Rights:  Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 */

package com.urbancode.air.plugin.AppScanSaaS

import java.util.Properties;
import java.util.concurrent.TimeUnit;

import com.urbancode.air.plugin.AppScanSaaS.RestClient
import com.urbancode.air.plugin.AppScanSaaS.ScanType

/**
 * Helper class used to generate the IRX file used in static scans.
 */
public class SastScanHelper {
    private static final long ARSA_GENERATION_TIMEOUT_MINUTES = 30

    public SastScanHelper() {}

	protected File generateARSA(String arsaToolDir, File scanDirectory, String configFile, boolean encrypt) {
		boolean isWindows = (System.getProperty('os.name') =~ /(?i)windows/).find()
		File arsaToolBin = new File(arsaToolDir, 'bin')
		String arsaExeName = isWindows? 'appscan.bat': 'appscan.sh'
		File arsaExe = new File(arsaToolBin, arsaExeName)

        if (!arsaExe.exists()) {
            println("[Error] $arsaExe not found. IRX file cannot be generated.")
            System.exit(1)
        }

		File workingDirectory = scanDirectory.isDirectory() ? scanDirectory : scanDirectory.getParentFile()
		if (workingDirectory == null || !workingDirectory.exists()) {
			println("[Error] Unable to resolve working directory for SAST input '${scanDirectory.absolutePath}'.")
			System.exit(1)
		}

		if (!scanDirectory.isDirectory()) {
			println("[Warning] SAST input '${scanDirectory.absolutePath}' is not a directory. " +
				"Using parent directory '${workingDirectory.absolutePath}' for IRX generation.")
		}

		String arsaName = scanDirectory.getName()
		if (!scanDirectory.isDirectory() && arsaName.lastIndexOf('.') > 0) {
			arsaName = arsaName.substring(0, arsaName.lastIndexOf('.'))
		}

		File arsaFile = new File(workingDirectory, arsaName + '.irx')

		if (arsaFile.exists()) {
			arsaFile.delete()
		}

		List<String> command = isWindows
			? ['cmd', '/c', arsaExe.absolutePath, 'prepare', '-n', arsaName]
			: [arsaExe.absolutePath, 'prepare', '-n', arsaName]

		if (configFile) {
			command.addAll(['-c', configFile])
			println("[OK] Using configuration file $configFile.")
		}

		if (!encrypt) {
			command.add('-ne')
		}

		println("[Action] Running the following command arguments: $command.")
		println("[Action] Generating IRX in directory: ${workingDirectory.absolutePath}.")

		ProcessBuilder processBuilder = new ProcessBuilder(command)
		processBuilder.directory(workingDirectory)
		processBuilder.redirectErrorStream(true)
		def process = processBuilder.start()

		StringBuffer outputBuffer = new StringBuffer()
		Thread outputReader = Thread.start {
			process.inputStream.withReader { reader ->
				reader.eachLine { line ->
					println("[ARSA] ${line}")
					outputBuffer.append(line).append(System.lineSeparator())
				}
			}
		}

		boolean finished = process.waitFor(ARSA_GENERATION_TIMEOUT_MINUTES, TimeUnit.MINUTES)
		if (!finished) {
			process.destroyForcibly()
			outputReader.join(2000)
			println("[Error] IRX generation command timed out after ${ARSA_GENERATION_TIMEOUT_MINUTES} minutes.")
			System.exit(1)
		}

		outputReader.join()

		def exitVal = process.exitValue()
		if (!exitVal) {
			println("[OK] Command ended with exitValue = $exitVal.")
		} else {
			println "[Error] Command failed with exitValue = $exitVal. Output:\n${outputBuffer.toString()}"
            System.exit(1)
		}

		return arsaFile
	}
}