/*
 * Copyright 2008 Google Inc.
 * 
 * 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 com.google.gwt.junit;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.junit.client.TimeoutException;
import com.google.gwt.junit.remote.BrowserManager;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.rmi.Naming;
import java.rmi.server.RMISocketFactory;
import java.security.Permission;

/**
 * Runs in web mode via browsers managed over RMI. This feature is experimental
 * and is not officially supported.
 */
class RunStyleRemoteWeb extends RunStyle {

  static class RMISocketFactoryWithTimeouts extends RMISocketFactory {
    private static boolean initialized;

    public static void init() throws IOException {
      if (!initialized) {
        RMISocketFactory.setSocketFactory(new RMISocketFactoryWithTimeouts());
        initialized = true;
      }
    }

    @Override
    public ServerSocket createServerSocket(int port) throws IOException {
      return RMISocketFactory.getDefaultSocketFactory().createServerSocket(port);
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException {
      Socket socket = new Socket();
      socket.connect(new InetSocketAddress(host, port), CONNECT_MS);
      socket.setSoTimeout(RESPONSE_TIMEOUT_MS);
      return socket;
    }
  }

  private static class RemoteBrowser {
    /**
     * Remote browser manager.
     */
    private final BrowserManager manager;

    /**
     * RMI URLs for the remote browser server.
     */
    private final String rmiUrl;
    /**
     * Reference to the remote browser processes.
     */
    private int token;

    public RemoteBrowser(BrowserManager manager, String rmiUrl) {
      this.manager = manager;
      this.rmiUrl = rmiUrl;
    }

    public BrowserManager getManager() {
      return manager;
    }

    public String getRmiUrl() {
      return rmiUrl;
    }

    public int getToken() {
      return token;
    }

    public void setToken(int token) {
      this.token = token;
    }
  }

  /**
   * Registered as a shutdown hook to make sure that any browsers that were not
   * finished are killed.
   */
  private class ShutdownCb extends Thread {

    @Override
    public synchronized void run() {
      for (RemoteBrowser remoteBrowser : remoteBrowsers) {
        int remoteToken = remoteBrowser.getToken();
        if (remoteToken > 0) {
          try {
            remoteBrowser.getManager().killBrowser(remoteToken);
          } catch (Exception e) {
            System.err.println("Error killing remote browser during shutdown: "
                + remoteBrowser.getRmiUrl());
            e.printStackTrace();
          }
          // We've done our best to kill it. Don't try anymore.
          remoteBrowser.setToken(0);
        }
      }
    }
  }

  private static final int CONNECT_MS = 10000;
  private static final int PING_KEEPALIVE_MS = 5000;

  // Larger values when debugging the unit test framework, so you
  // don't get spurious timeouts.
  // private static final int CONNECT_MS = 1000000;
  // private static final int PING_KEEPALIVE_MS = 500000;
  // private static final int RESPONSE_TIMEOUT_MS = 1000000;

  private static final int RESPONSE_TIMEOUT_MS = 10000;

  private RemoteBrowser[] remoteBrowsers;

  /**
   * Whether one of the remote browsers was interrupted.
   */
  private boolean wasInterrupted;

  /**
   * A separate lock to control access to {@link #wasInterrupted}. This keeps
   * the main thread calls into {@link #wasInterrupted()} from having to
   * synchronized on the containing instance and potentially block on RPC calls.
   * It is okay to take the {@link #wasInterruptedLock} while locking the
   * containing instance; it is NOT okay to do the opposite or deadlock could
   * occur.
   */
  private final Object wasInterruptedLock = new Object();

  /**
   * @param shell the containing shell
   */
  public RunStyleRemoteWeb(JUnitShell shell) {
    super(shell);
  }
  
  @Override
  public boolean initialize(String args) {
    if (args == null || args.length() == 0) {
      throw new JUnitFatalLaunchException(
          "RemoteWeb runstyle requires comma-separated RMI URLs");
    }
    String[] urls = args.split(",");
    try {
      RMISocketFactoryWithTimeouts.init();
    } catch (IOException e) {
      throw new JUnitFatalLaunchException("Error initializing RMISocketFactory",
          e);
    }
    System.setSecurityManager(new SecurityManager() {
      @Override
      public void checkPermission(Permission perm) {
      }

      @Override
      public void checkPermission(Permission perm, Object context) {
      }
    });
    int numClients = urls.length;
    shell.setNumClients(numClients);
    BrowserManager[] browserManagers = new BrowserManager[numClients];
    for (int i = 0; i < numClients; ++i) {
      long callStart = System.currentTimeMillis();
      try {
        browserManagers[i] = (BrowserManager) Naming.lookup(urls[i]);
      } catch (Exception e) {
        String message = "Error connecting to browser manager at " + urls[i];
        Throwable cause = e;
        if (e.getCause() instanceof SocketTimeoutException) {
          long elapsed = System.currentTimeMillis() - callStart;
          message += " - Timeout " + elapsed
              + "ms waiting to connect to browser manager.";
          cause = e.getCause();
        }
        System.err.println(message);
        cause.printStackTrace();
        throw new JUnitFatalLaunchException(message, cause);
      }
    }
    synchronized (this) {
      this.remoteBrowsers = new RemoteBrowser[browserManagers.length];
      for (int i = 0; i < browserManagers.length; ++i) {
        remoteBrowsers[i] = new RemoteBrowser(browserManagers[i], urls[i]);
      }
    }
    Runtime.getRuntime().addShutdownHook(new ShutdownCb());
    return true;
  }

  @Override
  public synchronized void launchModule(String moduleName)
      throws UnableToCompleteException {
    String url = shell.getModuleUrl(moduleName);

    for (RemoteBrowser remoteBrowser : remoteBrowsers) {
      long callStart = System.currentTimeMillis();
      try {
        int remoteToken = remoteBrowser.getToken();
        BrowserManager mgr = remoteBrowser.getManager();
        if (remoteToken != 0) {
          mgr.killBrowser(remoteToken);
        }
        remoteToken = mgr.launchNewBrowser(url, PING_KEEPALIVE_MS);
        remoteBrowser.setToken(remoteToken);
      } catch (Exception e) {
        Throwable cause = e.getCause();
        if (cause instanceof SocketTimeoutException) {
          long elapsed = System.currentTimeMillis() - callStart;
          getLogger().log(
              TreeLogger.ERROR,
              "Timeout: " + elapsed + "ms  launching remote browser at: "
                  + remoteBrowser.getRmiUrl(), e.getCause());
          throw new UnableToCompleteException();
        }
        getLogger().log(TreeLogger.ERROR,
            "Error launching remote browser at " + remoteBrowser.getRmiUrl(), e);
        throw new UnableToCompleteException();
      }
    }

    Thread keepAliveThread = new Thread() {
      @Override
      public void run() {
        do {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException ignored) {
          }
        } while (doKeepAlives());
      }
    };
    keepAliveThread.setDaemon(true);
    keepAliveThread.start();
  }

  @Override
  public boolean wasInterrupted() {
    synchronized (wasInterruptedLock) {
      return wasInterrupted;
    }
  }

  private synchronized boolean doKeepAlives() {
    for (RemoteBrowser remoteBrowser : remoteBrowsers) {
      if (remoteBrowser.getToken() > 0) {
        long callStart = System.currentTimeMillis();
        try {
          remoteBrowser.getManager().keepAlive(remoteBrowser.getToken(),
              PING_KEEPALIVE_MS);
        } catch (Exception e) {
          Throwable cause = e.getCause();
          String rmiUrl = remoteBrowser.getRmiUrl();
          if (cause instanceof SocketTimeoutException) {
            long elapsed = System.currentTimeMillis() - callStart;
            throw new TimeoutException("Timeout: " + elapsed
                + "ms  keeping alive remote browser at: " + rmiUrl,
                e.getCause());
          } else if (e instanceof IllegalStateException) {
            getLogger().log(TreeLogger.INFO,
                "Browser at: " + rmiUrl + " already exited.", e);
          } else {
            getLogger().log(TreeLogger.ERROR,
                "Error keeping alive remote browser at " + rmiUrl, e);
          }
          remoteBrowser.setToken(0);
          synchronized (wasInterruptedLock) {
            wasInterrupted = true;
          }
          break;
        }
      }
    }

    synchronized (wasInterruptedLock) {
      return !wasInterrupted;
    }
  }
}
