/*
 * Copyright 2013-present Facebook, 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.facebook.buck.plugin.intellij.commands;

import com.facebook.buck.plugin.intellij.commands.SocketClient.BuckPluginEventListener;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class BuckRunner {

  private static final Logger LOG = Logger.getInstance(BuckRunner.class);
  private static final String BUCK_BIN = "buck";
  private static final String BUCKD_BIN = "buckd";
  private static final String BUCK_EXTRA_JAVA_ARGS = "BUCK_EXTRA_JAVA_ARGS";
  private static final String BUCKD_HTTPSERVER_PORT = "-Dbuck.httpserver.port";

  private final File workingDirectory;
  private final ExecutorService executorService;
  private String buckPath;
  private Optional<String> buckdPath;
  private Optional<SocketClient> socket;
  private BuckPluginEventListener listener;
  private String stdout;
  private String stderr;

  public BuckRunner(Project project,
                    Optional<String> buckDirectory,
                    BuckPluginEventListener listener) throws BuckNotFound {
    Preconditions.checkNotNull(project);
    Preconditions.checkNotNull(buckDirectory);
    this.listener = Preconditions.checkNotNull(listener);
    buckdPath = Optional.absent();
    socket = Optional.absent();
    stdout = "";
    stderr = "";
    workingDirectory = new File(project.getBasePath());
    Preconditions.checkState(workingDirectory.isDirectory(),
        String.format("%s is not a valid working directory.", workingDirectory));
    executorService = Executors.newFixedThreadPool(2); // For stdout and stderr stream readers
    if (!detectBuck(buckDirectory)) {
      throw new BuckNotFound();
    }
  }

  public int execute(String... args) {
    ImmutableList<String> command = ImmutableList.<String>builder()
        .add(buckPath)
        .addAll(ImmutableList.copyOf(args))
        .build();
    if (socket.isPresent()) {
      socket.get().start();
    }
    int exitCode = execute(command, ImmutableMap.<String, String>of());
    if (socket.isPresent()) {
      socket.get().stop();
    }
    return exitCode;
  }

  public String getStdout() {
    return stdout;
  }

  public String getStderr() {
    return stderr;
  }

  private int execute(ImmutableList<String> command, ImmutableMap<String, String> environment) {
    Preconditions.checkNotNull(command);
    ProcessBuilder processBuilder = new ProcessBuilder(command);
    processBuilder.directory(workingDirectory);
    for (ImmutableMap.Entry<String, String> entry : environment.entrySet()) {
      processBuilder.environment().put(entry.getKey(), entry.getValue());
    }
    try {
      Process process = processBuilder.start();
      int exitCode;
      Future<String> stdoutFuture = readStream(process.getInputStream());
      Future<String> stderrFuture = readStream(process.getErrorStream());
      exitCode = process.waitFor();
      stdout = stdoutFuture.get();
      stderr = stderrFuture.get();
      return exitCode;
    } catch (IOException | ExecutionException | InterruptedException e) {
      LOG.error(e);
    }
    return -1;
  }

  private boolean detectBuck(Optional<String> buckDirectory) {
    if (buckDirectory.isPresent()) {
      String binDirectory = buckDirectory.get() + "/bin";
      if (detectBuckUnderDirectory(binDirectory)) {
        return true;
      }
    }
    // Find buck under system path
    String value = Strings.nullToEmpty(System.getenv("PATH"));
    for (String binDirectory : value.split(File.pathSeparator)) {
      if (detectBuckUnderDirectory(binDirectory)) {
        return true;
      }
    }
    return false;
  }

  private boolean detectBuckUnderDirectory(String binDirectory) {
    boolean success = false;
    File buck = new File(binDirectory, BUCK_BIN);
    if (buck.canExecute()) {
      buckPath = buck.getAbsolutePath();
      success = true;
    }
    File buckd = new File(binDirectory, BUCKD_BIN);
    if (buckd.canExecute()) {
      buckdPath = Optional.of(buckd.getAbsolutePath());
    }
    return success;
  }

  public void launchBuckd() {
    if (buckdPath.isPresent()) {
      try {
        int port = findAvailablePortForBuckdHttpServer();
        int exitCode = execute(ImmutableList.of(buckdPath.get()),
            ImmutableMap.<String, String>of(BUCK_EXTRA_JAVA_ARGS,
                String.format("%s=%d", BUCKD_HTTPSERVER_PORT, port)));
        if (exitCode != 0) {
          throw new Exception(getStderr());
        }
        socket = Optional.of(new SocketClient(port, listener));
      } catch (Exception e) {
        LOG.warn(String.format("Can not launch buckd: %s", e.getMessage()));
      }
    } else {
      LOG.warn("Can not find path to buckd, buck will be used barely.");
    }
  }

  private int findAvailablePortForBuckdHttpServer() throws IOException {
    ServerSocket server = new ServerSocket(0);
    int port = server.getLocalPort();
    server.close();
    return port;
  }

  private Future<String> readStream(final InputStream stream) {
    return executorService.submit(new Callable<String>() {
      @Override
      public String call() throws IOException {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
          StringBuilder output = new StringBuilder();
          char[] buffer = new char[64];
          int bytesRead;
          while ((bytesRead = reader.read(buffer)) != -1) {
            output.append(buffer, 0, bytesRead);
          }
          String outputString = output.toString();
          // Unify line separators
          return outputString.replace("\r\n", "\n");
        }
      }
    });
  }

  public class BuckNotFound extends Exception {
  }
}
