/*
 * 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.remote;

import com.google.gwt.util.tools.ArgHandler;
import com.google.gwt.util.tools.ArgHandlerFlag;
import com.google.gwt.util.tools.ArgHandlerString;
import com.google.gwt.util.tools.ToolBase;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 
 * Used to process arguments and start up instances of BrowserManagerServer.
 * Some of this logic used to be in BrowserManagerServer.main() and was moved
 * here so we could inherit argument parsing from the ToolBase class.
 */
class BrowserManagerServerLauncher extends ToolBase {

  private final class ArgHandlerPort extends ArgHandlerString {

    @Override
    public String getPurpose() {
      return "Controls the port for the RMI invocation (defaults to "
          + Registry.REGISTRY_PORT + ")";
    }

    @Override
    public String getTag() {
      return "-port";
    }

    @Override
    public String[] getTagArgs() {
      return new String[] {"port-number"};
    }

    @Override
    public boolean isRequired() {
      return false;
    }

    @Override
    public boolean setString(String value) {
      try {
        portArg = Integer.parseInt(value);
      } catch (NumberFormatException e) {
        logger.severe("The -port argument must be an integer value.  Got: "
            + value);
        return false;
      }
      return true;
    }
  }

  /**
   * Queues up requests to a single server so that only a single test runs at a time.
   */
  private class ArgHandlerSerializeRequests extends ArgHandlerFlag {

    public ArgHandlerSerializeRequests() {
      addTagValue("-serialize", true);
    }

    @Override
    public String getPurposeSnippet() {
      return "Queue up requests to a single server so that only a single "
          + "test runs at a time. Useful for a simple Firefox setup.";
    }

    @Override
    public String getLabel() {
      return "serializeRequests";
    }

    @Override
    public boolean setFlag(boolean value) {
      serializeArg = value;
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return serializeArg;
    }
  }

  /**
   * Handles the list of registration ids / machine names passed on the command
   * line.
   */
  private class ArgHandlerRegistration extends ArgHandler {

    @Override
    public String getPurpose() {
      return "Specify two arguments: a registration id used for the "
          + "RMI call and the browser launch command.";
    }

    @Override
    public String getTag() {
      return null;
    }

    @Override
    public String[] getTagArgs() {
      return new String[] {"registration-id", "path-to-browser-executable"};
    }

    @Override
    public int handle(String[] args, int startIndex) {
      // Consume 2 arguments
      if (args.length >= startIndex + 2) {
        BMSEntry entry = new BMSEntry(args[startIndex], args[startIndex + 1]);
        bmsList.add(entry);
        return 1;
      }
      return -1;
    }

    @Override
    public boolean isRequired() {
      return true;
    }
  }

  private static class BMSEntry {
    final String browserPath;
    final String registrationKey;

    BMSEntry(String registrationKeyIn, String browserPathIn) {
      registrationKey = registrationKeyIn;
      browserPath = browserPathIn;
    }
  }

  private static final Logger logger = Logger.getLogger(BrowserManagerServerLauncher.class.getName());

  private static final String USAGE = ""
      + "Manages local browser windows for a remote client using RMI.\n" + "\n"
      + "Pass in an even number of args, at least 2. The first argument\n"
      + "is a short registration name, and the second argument is the\n"
      + "executable to run when that name is used; for example,\n" + "\n"
      + "\tie6 \"C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE\"\n" + "\n"
      + "would register Internet Explorer to \"rmi://localhost/ie6\".\n"
      + "The third and fourth arguments make another pair, and so on.\n";

  private List<BMSEntry> bmsList = new ArrayList<BMSEntry>();
  private int portArg = Registry.REGISTRY_PORT;
  private boolean serializeArg = false;

  /**
   * Creates a new BrowserServerLauncher and registers argument handling
   * instances.
   */
  BrowserManagerServerLauncher() {
    registerHandler(new ArgHandlerPort());
    registerHandler(new ArgHandlerRegistration());
    registerHandler(new ArgHandlerSerializeRequests());
  }

  public boolean doProcessArgs(String[] args) {
    if (args.length == 0) {
      System.err.println(USAGE);
      return false;
    }
    return processArgs(args);
  }

  /**
   * This method should be invoked after argument parsing completes.
   */
  public void run() {
    Registry rmiRegistry = null;

    try {
      // Create an RMI registry so we don't need an external process.
      // Uses the default RMI port if no port is specified with the -port arg.
      rmiRegistry = LocateRegistry.createRegistry(portArg);
    } catch (RemoteException e) {
      logger.log(Level.SEVERE, "Couldn't bind RMI Registry to port " + portArg,
          e);
      System.exit(1);
    }

    logger.log(Level.ALL, "RMI registry ready on port " + portArg + ".");

    // Startup each of the registered servers on this machine.
    for (BMSEntry entry : bmsList) {
      BrowserManagerServer server = null;
      try {
        server = new BrowserManagerServer(entry.browserPath, serializeArg);
      } catch (RemoteException re) {
        logger.log(Level.SEVERE, entry.registrationKey
            + ": Error starting new BrowserManagerServer.", re);
        System.exit(2);
      }

      try {
        rmiRegistry.rebind(entry.registrationKey, server);
      } catch (RemoteException re) {
        logger.log(Level.SEVERE, entry.registrationKey + " server: " + server
            + " port: " + portArg + " Error on rebind to "
            + entry.registrationKey, re);
        System.exit(3);
      }
      logger.log(Level.INFO, "Server: " + entry.registrationKey
          + " started and awaiting connections.");
    }

    logger.log(Level.INFO, "All servers started.");
  }

  @Override
  protected String getDescription() {
    return USAGE;
  }

}
