/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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.android.jack.launcher;

import com.google.common.collect.Iterators;

import com.android.jack.server.api.v01.JackServer;
import com.android.jack.server.api.v01.LauncherHandle;
import com.android.jack.server.api.v01.NotInstalledException;
import com.android.jack.server.api.v01.ServerException;
import com.android.sched.util.FinalizerRunner;
import com.android.sched.util.UncomparableVersion;
import com.android.sched.util.Version;
import com.android.sched.util.stream.ByteStreamSucker;

import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;

/**
 * A launcher for the server.
 */
public final class ServerLauncher {

  private static class ServerInfo {
    private final int id;

    @Nonnull
    private final Version version;

    public ServerInfo(int id, @Nonnull Version version) {
      this.id = id;
      this.version = version;
    }
  }

  private static class TaskRunner implements Runnable {
    private static class Task {
      @Nonnull
      private final String name;
      @Nonnull
      private final Runnable runnable;

      public Task(@Nonnull String name, @Nonnull Runnable runnable) {
        this.name = name;
        this.runnable = runnable;
      }
    }
    @Nonnull
    private final BlockingQueue<Task> taskQueue = new LinkedBlockingQueue<>();

    @Override
    public void run() {
      try {
        while (true) {
          Task next = taskQueue.take();
          Thread thread = new Thread(next.runnable, next.name);
          thread.setDaemon(false);
          thread.start();
        }
      } catch (InterruptedException e) {
        logger.log(Level.FINE, "Thread " + Thread.currentThread().getName() + " interrupted");
        Thread.currentThread().interrupt();
      }
    }

    void executeTask(@Nonnull String name, @Nonnull Runnable task) {
      taskQueue.add(new Task(name, task));
    }
  }

  private class RunServerTask implements Runnable {
    @Nonnull
    private final ServerInfo serverInfo;

    @Nonnull
    private final Map<String, Object> parameters;

    public RunServerTask(@Nonnull ServerInfo serverInfo,
        @Nonnull Map<String, Object> parameters) {
      this.serverInfo = serverInfo;
      this.parameters = parameters;
    }

    @Override
    public void run() {
      File serverJar = getServerJar(serverDir, serverInfo.id);
      try {
        JackServer server = loadServer(serverJar);
        synchronized (currentServerLock) {
          assert currentServer == null;
          currentServer = server;
        }
        logger.log(Level.FINE, "Starting server " + serverInfo.version.getVerboseVersion() +
            " from " + serverJar.getName());
        server.setHandle(new ServerLauncherHandle());
        server.run(parameters);
        logger.log(Level.FINE, "Server " + serverInfo.version.getVerboseVersion() +
            " from " + serverJar.getName() + " ended");
      } catch (ServerException e) {
        logger.log(Level.SEVERE, "Server " + serverInfo.version.getVerboseVersion() +
            " from " + serverJar.getName() + " error: " + e.getMessage(), e);
      } catch (InterruptedException e) {
        logger.log(Level.FINE, "Server " + serverInfo.version.getVerboseVersion() +
            " from " + serverJar.getName() + " ended on interruption");
        Thread.currentThread().interrupt();
      } finally {
        decrementServerCount();
      }
    }
  }

  private static class Deleter implements Runnable {
    @Nonnull
    private final File[] toDelete;

    private Deleter(@Nonnull File[] toDelete) {
      this.toDelete = toDelete;
    }

    @Override
    public void run() {
      for (File file : toDelete) {
        if (!file.delete()) {
          logger.log(Level.WARNING, "Failed to delete file '" + file.getPath() + "'");
        } else {
          logger.log(Level.FINE, "Deleted file '" + file.getPath() + "'");
        }
      }
    }
  }

  private static class NotAServerJarFileName extends Exception {
    private static final long serialVersionUID = 1L;
  }

  private class ServerLauncherHandle implements LauncherHandle {

    @Override
    @Nonnull
    public File getServerDir() {
      return ServerLauncher.this.getServerDir();
    }

    @Override
    public void replaceServer(@Nonnull InputStream newServer,
        @Nonnull Map<String, Object> parameters, boolean forced)
        throws IOException, ServerException, NotInstalledException {
      ServerLauncher.this.replaceServer(newServer, parameters, forced);
    }

    @Override
    @Nonnull
    public ClassLoader getLauncherClassLoader() {
      return ServerLauncher.class.getClassLoader();
    }

    @Override
    @Nonnull
    public void deleteFilesOnGarbage(@Nonnull File[] filesToDelete, @Nonnull Object watched) {
      finalizer.registerFinalizer(new Deleter(filesToDelete), watched);
    }
  }

  @Nonnull
  private static final Logger logger = Logger.getLogger(ServerLauncher.class.getName());

  @Nonnull
  private static final String HELP = "--help";

  @Nonnull
  private static final String VERSION = "--version";

  @Nonnull
  private static final String TMP_SUFFIX = ".tmp";

  private static final int ABORT_EXIT_CODE = 255;
  /**
   * Usage, syntax or configuration file error.
   */
  public static final int FAILURE_USAGE = 2;

  @Nonnull
  private static final String DEFAULT_JACK_DIR = ".";

  @Nonnull
  private static final Pattern SERVER_JAR_PATTERN = Pattern.compile("server-(\\d+)\\.jar");

  @Nonnull
  private final FinalizerRunner finalizer = new FinalizerRunner("Launcher finalizer");

  @Nonnull
  private final File serverDir;

  /**
   * Used to synchronize access to currentServerInfo and currentServer.
   */
  @Nonnull
  private final Object currentServerLock = new Object();
  @CheckForNull
  private ServerInfo currentServerInfo;
  @CheckForNull
  private JackServer currentServer;

  @Nonnegative
  private int serverCount;

  @Nonnull
  private final Object serverCountLock = new Object();

  @Nonnull
  private final TaskRunner taskRunner = new TaskRunner();

  public static void main(@Nonnull String[] args) {
    if (args.length == 0) {
      Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
          logger.log(Level.SEVERE, "Uncaught exception in thread '" + t.getName() + "'", e);
          abort("Internal error");
        }
      });
      String jackDir = System.getProperty("jack.home", DEFAULT_JACK_DIR);
      try {
        new ServerLauncher(new File(jackDir)).run();
      } catch (ServerException e) {
        abort("Failed to start server: " + e.getMessage());
      } catch (InterruptedException e) {
        logger.log(Level.FINE, "ServerLauncher was interrupted");
      }
    } else if (args.length == 1) {
      String command = args[0];
      switch (command) {
        case HELP:
          printHelp(System.out);
          break;
        case VERSION:
          try {
            printVersion(System.out);
          } catch (IOException e) {
            e.printStackTrace();
            abort("Failed to read version");
          }
          break;
        default:
          printHelp(System.err);
          System.exit(FAILURE_USAGE);
          break;
      }
    } else {
      printHelp(System.err);
      System.exit(FAILURE_USAGE);
    }
  }

  private static void printVersion(@Nonnull PrintStream printStream) throws IOException {
    Version version = new Version("jack-launcher", ServerLauncher.class.getClassLoader());
    printStream.println("Jack server launcher.");
    printStream.println("Version: " + version.getVerboseVersion() + '.');
  }

  private static void printHelp(@Nonnull PrintStream printStream) {
    printStream.println("Usage: <options>");
    printStream.println("Start server.");
    printStream.println();
    printStream.println("Options:");
    printStream.println(" --help     : display help");
    printStream.println(" --version  : display version");
  }

  public ServerLauncher(@Nonnull File serverDir) {
    this.serverDir = serverDir;
  }

  public void run() throws ServerException, InterruptedException {
    Thread taskThread = new Thread(taskRunner, "Task runner");
    taskThread.setDaemon(true);
    taskThread.start();

    File[] serverDirFiles = serverDir.listFiles(new FileFilter() {
      @Override
      public boolean accept(File pathname) {
        return pathname.isFile();
      }
    });
    if (serverDirFiles == null) {
      throw new ServerException("Failed to list server install directory '" + serverDir + "'");
    }

    List<Integer> serverIds = new LinkedList<Integer>();
    for (File candidate : serverDirFiles) {
      try {
        serverIds.add(Integer.valueOf(getServerId(candidate)));
      } catch (NotAServerJarFileName e) {
        // Not a server jar, is it a forgotten tmp?
        if (candidate.getName().endsWith(TMP_SUFFIX)) {
          deleteFile(candidate);
        }
      }
    }
    if (serverIds.size() == 0) {
      throw new ServerException("No installed Jack server");
    }
    Collections.sort(serverIds);
    Iterator<Integer> iteratorAll = serverIds.iterator();
    Iterator<Integer> toDeleteIterator = Iterators.limit(iteratorAll, serverIds.size() - 1);
    while (toDeleteIterator.hasNext()) {
      deleteFile(getServerJar(serverDir, toDeleteIterator.next().intValue()));
    }

    int serverId = iteratorAll.next().intValue();
    try {
      startInitialServer(serverDir, serverId);
    } catch (IOException e) {
      throw new ServerException("Failed to start installed server", e);
    }

    waitServers();
    taskThread.interrupt();
    finalizer.shutdown();
  }

  private void waitServers() throws InterruptedException {
    synchronized (serverCountLock) {
      while (serverCount > 0) {
        serverCountLock.wait();
      }
    }
    logger.log(Level.FINE, "Last server exited");
  }

  private void startInitialServer(@Nonnull File serverDir, @Nonnegative final int serverId)
      throws ServerException, IOException {
    // Don't inline in long living method, it could prevent the server to be garbaged because of
    // locals
    File serverJar = getServerJar(serverDir, serverId);
    final JackServer server = loadServer(serverJar);
    synchronized (currentServerLock) {
      currentServer = server;
      server.setHandle(new ServerLauncherHandle());

      currentServerInfo = new ServerInfo(serverId,
          new Version("jack-server", server.getClass().getClassLoader()));
    }

    incrementServerCount();
    taskRunner.executeTask("Server " + serverId, new Runnable() {
      @Override
      public void run() {
        logger.log(Level.FINE, "Starting server " + serverId);
        try {
          server.onSystemStart();
          server.run(new HashMap<String, Object>());
          logger.log(Level.FINE, "Server " + serverId + " ended");
        } catch (ServerException e) {
          logger.log(Level.SEVERE, "Server " + serverId + " Exception", e);
        } catch (InterruptedException e) {
          logger.log(Level.FINE, "Server " + serverId + " ended on interruption");
          Thread.currentThread().interrupt();
        } finally {
          decrementServerCount();
        }
      }
    });
  }

  private static File getServerJar(@Nonnull File serverDir, @Nonnegative int serverId) {
    return new File(serverDir, "server-" + serverId + ".jar");
  }

  @Nonnull
  private static JackServer loadServer(@Nonnull File jar) throws ServerException {
    ClassLoader classLoader;
    try {
      classLoader = new URLClassLoader(new URL[]{jar.toURI().toURL()},
          ServerLauncher.class.getClassLoader());
    } catch (IOException e) {
      throw new ServerException("Failed to open jar '" + jar.getPath() + "'", e);
    }
    ServiceLoader<JackServer> serviceLoader = ServiceLoader.load(JackServer.class, classLoader);
    try {
      JackServer server = serviceLoader.iterator().next();
      assert server.getClass().getClassLoader() == classLoader;
      return server;
    } catch (NoSuchElementException e) {
      throw new ServerException("Jar '" + jar.getPath() + "' does not define a server");
    } catch (ServiceConfigurationError e) {
      throw new ServerException(
          "Jar '" + jar.getPath() + "' does not define a valid server: " + e.getMessage(), e);
    }
  }

  private static void deleteFile(@Nonnull File file) {
    if (!file.delete()) {
      logger.log(Level.WARNING, "Failed to delete file '" + file.getPath() + "'");
    }
  }

  private static void abort(@Nonnull String message) {
    System.err.println(message);
    System.exit(ABORT_EXIT_CODE);
  }

  private static int getServerId(File serverJar) throws NotAServerJarFileName {
    Matcher matcher = SERVER_JAR_PATTERN.matcher(serverJar.getName());
    if (!matcher.matches()) {
      throw new NotAServerJarFileName();
    }
    return Integer.parseInt(matcher.group(1));
  }

  @Nonnull
  public File getServerDir() {
    return serverDir;
  }

  private void replaceServer(@Nonnull InputStream jarIn, @Nonnull Map<String, Object> parameters,
      boolean forced)
      throws IOException, ServerException, NotInstalledException {
    FileOutputStream out = null;
    File tmpInstall = null;
    synchronized (currentServerLock) {
      try {
        tmpInstall = File.createTempFile("jacklauncher-", TMP_SUFFIX, serverDir);
        out = new FileOutputStream(tmpInstall);
        new ByteStreamSucker(jarIn, out).suck();
        out.close();
        out = null;

        ClassLoader tmpLoader;
        try {
          tmpLoader = new URLClassLoader(new URL[]{tmpInstall.toURI().toURL()},
              ServerLauncher.class.getClassLoader());
        } catch (IOException e) {
          throw new ServerException("Failed to open jar '" + tmpInstall.getPath() + "'", e);
        }

        Version candidateVersion = new Version("jack-server", tmpLoader);
        assert currentServerInfo != null;
        Version currentVerion = currentServerInfo.version;

        if (!forced) {
          try {
            if (!candidateVersion.isNewerThan(currentVerion)) {
              if (candidateVersion.equals(currentVerion)) {
                logger.log(Level.INFO, "Server version "
                    + currentVerion.getVerboseVersion() + " was already installed");
                return;
              } else {
                throw new NotInstalledException("Not installing server "
                    + candidateVersion.getVerboseVersion()
                    + " since it is not newer than current server "
                    + currentServerInfo.version.getVerboseVersion());
              }
            }
          } catch (UncomparableVersion e) {
            if (!candidateVersion.isComparable()) {
              throw new NotInstalledException("Not installing server '"
                  + candidateVersion.getVerboseVersion() + "' without force request");
            }
            // else: current is experimental or eng, candidate is not, lets proceed
          }
        }

        assert currentServerInfo != null;
        int newServerId = currentServerInfo.id + 1;
        File newInstalledServer = getServerJar(serverDir, newServerId);
        if (!tmpInstall.renameTo(newInstalledServer)) {
          throw new IOException("Failed to rename '" + tmpInstall + "' to '" + newInstalledServer
              + "'");
        }
        tmpInstall = null;

        File replacedServerJar = getServerJar(serverDir, currentServerInfo.id);
        assert currentServer != null;
        finalizer.registerFinalizer(new Deleter(new File[]{replacedServerJar}),
            currentServer.getClass().getClassLoader());
        currentServerInfo = new ServerInfo(newServerId, candidateVersion);
      } finally {
        if (out != null) {
          try {
            out.close();
          } catch (IOException e) {
            logger.log(Level.WARNING, "Exception during close", e);
          }
        }
        if (tmpInstall != null) {
          if (!tmpInstall.delete()) {
            logger.log(Level.WARNING, "Failed to delete temp file '" + tmpInstall + "'");
          }
        }

        currentServer = null;
        assert currentServerInfo != null;
        logger.log(Level.FINE, "Starting server "  + currentServerInfo.version.getVerboseVersion());
        incrementServerCount();
        assert currentServerInfo != null;
        taskRunner.executeTask("Server " + currentServerInfo.id,
            new RunServerTask(currentServerInfo, parameters));
      }
    }
  }

  private void incrementServerCount() {
    synchronized (serverCountLock) {
      serverCount++;
    }
  }

  private void decrementServerCount() {
    synchronized (serverCountLock) {
      serverCount--;
      serverCountLock.notifyAll();
    }
  }

}
