/*
 * 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.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();
    return execute(command, ImmutableMap.<String, String>of());
  }

  public int executeAndListenToWebsocket(String... args) {
    if (socket.isPresent()) {
      socket.get().start();
    }
    int exitCode = execute(args);
    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 e) {
      LOG.error(e);
    } catch (ExecutionException e) {
      LOG.error(e);
    } catch (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 {
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        try {
          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");
        } finally {
          reader.close();
        }
      }
    });
  }

  public class BuckNotFound extends Exception {
  }
}
