import static org.junit.Assert.fail;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.junit.Test;

/**
 * Test case which validates that the publishing script runs
 * 
 * @author Horia Chiorean (hchiorea@redhat.com)
 */
public class RestClientScriptTest {
   
    @Test
    public void shouldRunScript() throws Exception {
        File testFile = writeTestFile();
        boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");
        File activeDir = new File("target/server/rest-client");
        String scriptName = isWindows ?  "restclient.bat" : "restclient.sh";
        Path script = Paths.get(activeDir.getAbsolutePath(), scriptName);
        File scriptOutput = new File("target/script_output.txt");
        if (scriptOutput.exists()) {
            scriptOutput.delete();
        }
        Path scriptOutputPath = scriptOutput.toPath();
        // the server is set up via Maven and Cargo
        ProcessBuilder processBuilder = new ProcessBuilder(script.toString(),
                                                           "--server", "http://localhost:8090/modeshape-rest",
                                                           "--file", testFile.getAbsolutePath(),
                                                           "--repo", "repo",
                                                           "--workspacepath","/",
                                                           "--username", "dnauser",
                                                           "--pwd", "password")
                .redirectOutput(scriptOutput)
                .redirectErrorStream(true);
        final Process process = processBuilder.start();
        try (BufferedReader reader = Files.newBufferedReader(scriptOutputPath, Charset.defaultCharset())) {
            while (true) {
                try {
                    // check if the process has finished
                    String line = reader.readLine();
                    if (line != null && isKeyPressLine(line)) {
                        // we've reached the end
                        break;
                    }
                    int exitValue = process.exitValue();
                    if (exitValue != 0) {
                        fail("The script process did not exit successfully. See " + scriptOutput + " for more info.");
                    }
                    // if we made it this far the process has completed
                    break;
                } catch (IllegalThreadStateException e) {
                    // still running
                    Thread.sleep(100);
                }
            }
        } finally {
            process.destroy();    
        }
       
        List<String> lines = Files.readAllLines(scriptOutputPath, Charset.defaultCharset());
        String lastLine = lines.get(lines.size() - 1);
        if (isKeyPressLine(lastLine)) {
            // remove the Press... line
            lines.remove(lines.size() - 1);
            lastLine = lines.get(lines.size() - 1);
        }
        
        if (!lastLine.toLowerCase().contains("successfully")) {
            fail("script did not publish successfully: " + lastLine + ". See " + scriptOutput + " for more info.");
        }
    }
    
    private boolean isKeyPressLine(String line) {
        return line.startsWith("Press");
    }
    
    private File writeTestFile() throws IOException {
        File testFile = new File("target/modeshape_client_publishing_test.txt");
        if (testFile.exists()) {
            testFile.delete();
        }
        try (BufferedWriter writer = Files.newBufferedWriter(testFile.toPath(), Charset.defaultCharset(), StandardOpenOption.CREATE)) {
            writer.write("publishing test at: " + SimpleDateFormat.getDateTimeInstance().format(new Date()));
            writer.newLine();
            writer.flush();
        }
        return testFile;
    }
}
