/*
 * 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 org.netbeans.libs.jstestdriver;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.StringTokenizer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.login.Configuration;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.netbeans.api.extexecution.ExecutionDescriptor;
import org.netbeans.api.extexecution.ExecutionService;
import org.netbeans.api.extexecution.ExternalProcessBuilder;
import org.netbeans.api.extexecution.input.InputProcessor;
import org.netbeans.api.extexecution.print.LineConvertor;
import org.netbeans.libs.jstestdriver.api.BrowserInfo;
import org.netbeans.libs.jstestdriver.api.ServerListener;
import org.netbeans.libs.jstestdriver.api.TestListener;
import org.openide.modules.InstalledFileLocator;
import org.openide.util.Exceptions;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
import org.openide.windows.IOProvider;

// TODO: initially this implementation was in a different module;
// perhaps refactor back and drop the JsTestDriverImplementation
public class JsTestDriverImpl implements JsTestDriverImplementation {

    private boolean running = false;
    private Future task;
    private boolean externallyStarted;
    private static final Logger LOGGER = Logger.getLogger(JsTestDriverImpl.class.getName());
    private static RequestProcessor RP = new RequestProcessor("re-fire js-test-driver events");

    public JsTestDriverImpl() {
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
                if (task != null) {
                    task.cancel(true);
                }
            }
        }));
    }
    
    private boolean wasStartedExternally(int port) {
        try {
            URL u = new URL("http://localhost:"+port);
            URLConnection conn = u.openConnection();
            conn.connect();
            return true;
        } catch (IOException ex) {
            return false;
        }
    }
    
    private static String getJavaBinary() {
        String javaHome = System.getProperty("java.home");
        String javaBinary = Utilities.isWindows() ? "java.exe" : "java"; // NOI18N
        return javaHome + File.separator + "bin" + File.separator + javaBinary;
        
    }
    
    @Override
    public void startServer(File jsTestDriverJar, int port, boolean strictMode, ServerListener listener) {
        if (wasStartedExternally(port)) {
            externallyStarted = true;
            IOProvider.getDefault().getIO("js-test-driver Server", false).getOut().
                    println("Port "+port+" is busy. Server was started outside of the IDE.");
            return;
        }
        ExecutionDescriptor descriptor = new ExecutionDescriptor().
                controllable(false).
//                outLineBased(true).
//                errLineBased(true).
                outProcessorFactory(new ServerInputProcessorFactory(listener)).
                frontWindowOnError(true);
        File extjar = InstalledFileLocator.getDefault().locate("modules/ext/libs.jstestdriver-ext.jar", "org.netbeans.libs.jstestdriver", false); // NOI18N
        ExternalProcessBuilder processBuilder = new ExternalProcessBuilder(getJavaBinary()).
            addArgument("-cp").
            addArgument(jsTestDriverJar.getAbsolutePath()+File.pathSeparatorChar+extjar.getAbsolutePath()).
            addArgument("org.netbeans.libs.jstestdriver.ext.StartServer").
            addArgument(""+port).
            addArgument(""+strictMode);
        ExecutionService service = ExecutionService.newService(processBuilder, descriptor, "js-test-driver Server");
        task = service.run();
        running = true;
    }

    @Override
    public void stopServer() {
        assert running : "server is not running";
        task.cancel(true);
        task = null;
        running = false;
    }

    @Override
    public boolean isRunning() {
        return running || externallyStarted;
    }
    
    @Override
    public boolean wasStartedExternally() {
        return externallyStarted;
    }

    @Override
    public void runTests(File jsTestDriverJar, String serverURL, boolean strictMode, File baseFolder, File configFile, 
            String testsToRun, final TestListener listener, final LineConvertor lineConvertor) {
        ExecutionDescriptor descriptor = new ExecutionDescriptor().
                controllable(false).
//                outLineBased(true).
//                errLineBased(true).
                outProcessorFactory(new TestRunInputProcessorFactory(listener)).
                outConvertorFactory(new ExecutionDescriptor.LineConvertorFactory() {
                    @Override
                    public LineConvertor newLineConvertor() {
                        return lineConvertor;
                    }
                }).
                frontWindowOnError(true);
        File extjar = InstalledFileLocator.getDefault().locate("modules/ext/libs.jstestdriver-ext.jar", "org.netbeans.libs.jstestdriver", false); // NOI18N
        ExternalProcessBuilder processBuilder = new ExternalProcessBuilder(getJavaBinary()).
            addArgument("-cp").
            addArgument(jsTestDriverJar.getAbsolutePath()+File.pathSeparatorChar+extjar.getAbsolutePath()).
            addArgument("org.netbeans.libs.jstestdriver.ext.RunTests").
            addArgument(serverURL).
            addArgument(baseFolder.getAbsolutePath()).
            addArgument(configFile.getAbsolutePath()).
            addArgument(testsToRun).
            addArgument(""+strictMode);
        ExecutionService service = ExecutionService.newService(processBuilder, descriptor, "Running JS unit tests");
        try {
            service.run().get();
        } catch (InterruptedException ex) {
            Exceptions.printStackTrace(ex);
        } catch (ExecutionException ex) {
            Exceptions.printStackTrace(ex);
        }
        RP.post(new Runnable() {
        @Override
            public void run() {
                listener.onTestingFinished();
            }
        });
    }

    private static class ServerInputProcessorFactory implements ExecutionDescriptor.InputProcessorFactory {

        private ServerListener listener;

        public ServerInputProcessorFactory(ServerListener listener) {
            this.listener = listener;
        }
        
        @Override
        public InputProcessor newInputProcessor(InputProcessor defaultProcessor) {
            return new ServerInputProcessor(defaultProcessor, listener);
        }
        
    }
    
    private static class ServerInputProcessor implements InputProcessor {

        private InputProcessor delegate;
        private ServerListener listener;

        public ServerInputProcessor(InputProcessor delegate, ServerListener listener) {
            this.delegate = delegate;
            this.listener = listener;
        }
        
        @Override
        public void processInput(char[] chars) throws IOException {
            String s = new String(chars);
            if (s.indexOf("msg.server.started") != -1) {
                s = s.replace("msg.server.started", "Server has started");
                delegate.processInput(s.toCharArray());
                listener.serverStarted();
            } else {
                delegate.processInput(chars);
            }
        }

        @Override
        public void reset() throws IOException {
            delegate.reset();
        }

        @Override
        public void close() throws IOException {
            delegate.close();
        }
        
    }
    
    private static class TestRunInputProcessorFactory implements ExecutionDescriptor.InputProcessorFactory {

        private TestListener listener;

        public TestRunInputProcessorFactory(TestListener listener) {
            this.listener = listener;
        }
        
        @Override
        public InputProcessor newInputProcessor(InputProcessor defaultProcessor) {
            return new TestRunInputProcessor(defaultProcessor, listener);
        }
        
    }
    
    private static class TestRunInputProcessor implements InputProcessor {

        private InputProcessor delegate;
        private TestListener listener;

        public TestRunInputProcessor(InputProcessor delegate, TestListener listener) {
            this.delegate = delegate;
            this.listener = listener;
        }
        
        @Override
        public void processInput(char[] chars) throws IOException {
            String s = new String(chars);
            processPossibleBlockOfLines(s);
        }
        
        private void processPossibleBlockOfLines(String s) throws IOException {
            try {
                StringTokenizer st = new StringTokenizer(s, "\n");
                while (st.hasMoreTokens()) {
                    String ss = processSingleLine(st.nextToken())+"\n";
                    delegate.processInput(ss.toCharArray());
                }
            } catch (Throwable t) {
                LOGGER.log(Level.SEVERE, "something went wrong: "+s, t);
            }
        }
        private String processSingleLine(String s) throws IOException {
            int start = s.indexOf("nb-easel-json:{");
            if (start != -1) {
                int end = s.lastIndexOf("}");
                String command = s.substring(start+14, end+1);
                Object o = JSONValue.parse(command);
                if (o == null) {
                    LOGGER.log(Level.SEVERE, "cannot parse following JSON: "+command + " original message: "+s, new IOException("cannot parse"));
                } else {
                    assert o instanceof JSONObject : "must be JSONObject: "+o+" "+o.getClass();
                    JSONObject json = (JSONObject)o;
                    final TestListener.TestResult tr = new TestListener.TestResult(
                            new BrowserInfo((String)json.get("browserName"), (String)json.get("browserVersion"), (String)json.get("browserOS")),
                            (String)json.get("result"), (String)json.get("message"), (String)json.get("log"), 
                            (String)json.get("testCase"), (String)json.get("testName"), ((Number)json.get("duration")).longValue(),
                            (String)json.get("stack"));
                    StringBuilder test = new StringBuilder();
                    test.append(tr.getTestCaseName() + " - " + tr.getTestName() + " " +
                            tr.getResult().toString().toUpperCase()+" in "+tr.getDuration()+"ms (" +tr.getBrowserInfo().getName()+ 
                            ","+tr.getBrowserInfo().getOs() + ","+tr.getBrowserInfo().getVersion()+")");
                    if (tr.getStack().length() > 0) {
                        test.append("\n"+tr.getStack());
                    }
                    if (tr.getLog().length() > 0) {
                        test.append("\n"+tr.getLog());
                    }
                    if (tr.getMessage().length() > 0) {
                        test.append("\n"+tr.getMessage());
                    }
                    s = s.substring(0, start)+test.toString()+s.substring(end+1);
                    RP.post(new Runnable() {
                    @Override
                        public void run() {
                            listener.onTestComplete(tr);
                        }
                    });
                    return s;
                }
            }
            return s;
        }

        @Override
        public void reset() throws IOException {
            delegate.reset();
        }

        @Override
        public void close() throws IOException {
            delegate.close();
        }
        
    }
}
