// Copyright (C) 2013 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.google.gerrit.acceptance;

import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.pgm.Daemon;
import com.google.gerrit.pgm.Init;
import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.util.SocketUtil;
import com.google.inject.Injector;
import com.google.inject.Module;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Callable;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class GerritServer {

  /** Returns fully started Gerrit server */
  static GerritServer start(Config base) throws Exception {
    final File site = initSite(base);
    final CyclicBarrier serverStarted = new CyclicBarrier(2);
    final Daemon daemon = new Daemon(new Runnable() {
      public void run() {
        try {
          serverStarted.await();
        } catch (InterruptedException e) {
          throw new RuntimeException(e);
        } catch (BrokenBarrierException e) {
          throw new RuntimeException(e);
        }
      }
    });

    ExecutorService daemonService = Executors.newSingleThreadExecutor();
    daemonService.submit(new Callable<Void>() {
      public Void call() throws Exception {
        int rc = daemon.main(new String[] {"-d", site.getPath(), "--headless" });
        if (rc != 0) {
          System.out.println("Failed to start Gerrit daemon. Check "
              + site.getPath() + "/logs/error_log");
          serverStarted.reset();
        }
        return null;
      };
    });

    serverStarted.await();
    System.out.println("Gerrit Server Started");

    Injector i = createTestInjector(daemon);
    return new GerritServer(site, i, daemon, daemonService);
  }

  private static File initSite(Config base) throws Exception {
    File tmp = TempFileUtil.createTempDirectory();
    Init init = new Init();
    int rc = init.main(new String[] {
        "-d", tmp.getPath(), "--batch", "--no-auto-start",
        "--skip-plugins"});
    if (rc != 0) {
      throw new RuntimeException("Couldn't initialize site");
    }

    InetSocketAddress http = newPort();
    InetSocketAddress sshd = newPort();
    String url = "http://" + format(http) + "/";
    MergeableFileBasedConfig cfg = new MergeableFileBasedConfig(
        new File(new File(tmp, "etc"), "gerrit.config"),
        FS.DETECTED);
    cfg.load();
    cfg.merge(base);
    cfg.setString("gerrit", null, "canonicalWebUrl", url);
    cfg.setString("httpd", null, "listenUrl", url);
    cfg.setString("sshd", null, "listenAddress", format(sshd));
    cfg.setString("cache", null, "directory", null);
    cfg.setBoolean("sendemail", null, "enable", false);
    cfg.setInt("cache", "projects", "checkFrequency", 0);
    cfg.setInt("plugins", null, "checkFrequency", 0);
    cfg.save();
    return tmp;
  }

  private static String format(InetSocketAddress s) {
    return String.format("%s:%d", s.getAddress().getHostAddress(), s.getPort());
  }

  private static Injector createTestInjector(Daemon daemon) throws Exception {
    Injector sysInjector = get(daemon, "sysInjector");
    Module module = new FactoryModule() {
      @Override
      protected void configure() {
        bind(AccountCreator.class);
      }
    };
    return sysInjector.createChildInjector(module);
  }

  @SuppressWarnings("unchecked")
  private static <T> T get(Object obj, String field) throws SecurityException,
      NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    Field f = obj.getClass().getDeclaredField(field);
    f.setAccessible(true);
    return (T) f.get(obj);
  }

  private static final InetSocketAddress newPort() throws IOException {
    ServerSocket s = new ServerSocket(0, 0, getLocalHost());
    try {
      return (InetSocketAddress) s.getLocalSocketAddress();
    } finally {
      s.close();
    }
  }

  private static InetAddress getLocalHost() throws UnknownHostException {
    try {
      return InetAddress.getLocalHost();
    } catch (UnknownHostException e1) {
      try {
        return InetAddress.getByName("localhost");
      } catch (UnknownHostException e2) {
        return InetAddress.getByName("127.0.0.1");
      }
    }
  }

  private File sitePath;
  private Daemon daemon;
  private ExecutorService daemonService;
  private Injector testInjector;
  private String url;
  private InetSocketAddress sshdAddress;
  private InetSocketAddress httpAddress;

  private GerritServer(File sitePath, Injector testInjector, Daemon daemon,
      ExecutorService daemonService) throws IOException, ConfigInvalidException {
    this.sitePath = sitePath;
    this.testInjector = testInjector;
    this.daemon = daemon;
    this.daemonService = daemonService;

    FileBasedConfig cfg = new FileBasedConfig(
        new File(new File(sitePath, "etc"), "gerrit.config"),
        FS.DETECTED);
    cfg.load();

    url = cfg.getString("gerrit", null, "canonicalWebUrl");
    URI uri = URI.create(url);

    sshdAddress = SocketUtil.resolve(
        cfg.getString("sshd", null, "listenAddress"),
        0);
    httpAddress = new InetSocketAddress(uri.getHost(), uri.getPort());
  }

  String getUrl() {
    return url;
  }

  InetSocketAddress getSshdAddress() {
    return sshdAddress;
  }

  InetSocketAddress getHttpAddress() {
    return httpAddress;
  }

  Injector getTestInjector() {
    return testInjector;
  }

  void stop() throws Exception {
    LifecycleManager manager = get(daemon, "manager");
    System.out.println("Gerrit Server Shutdown");
    manager.stop();
    daemonService.shutdownNow();
    daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
    TempFileUtil.recursivelyDelete(sitePath);
    RepositoryCache.clear();
  }
}
