/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

#include "GfshExecute.h"

#include <mutex>

#include <boost/log/trivial.hpp>

#if defined(_WINDOWS)
std::mutex g_child_mutex;
#endif

using boost::process::args;
using boost::process::child;
using boost::process::environment;
using boost::process::ipstream;
using boost::process::std_err;
using boost::process::std_out;

GfshExecuteException::GfshExecuteException(std::string message, int returnCode)
    : apache::geode::client::Exception(message), returnCode_(returnCode) {}

GfshExecuteException::~GfshExecuteException() {}

std::string GfshExecuteException::getName() const {
  return "GfshExecuteException";
}

int GfshExecuteException::getGfshReturnCode() { return returnCode_; }

void GfshExecute::execute(const std::string &command, const std::string &user,
                          const std::string &password, const std::string &keyStorePath,
                          const std::string &trustStorePath,
                          const std::string &keyStorePassword,
                          const std::string &trustStorePassword) {
  BOOST_LOG_TRIVIAL(info) << "Gfsh::execute: " << command;

  std::vector<std::string> commands;
  if (!connection_.empty()) {
    commands.push_back("-e");
    commands.push_back(connection_);
  }
  commands.push_back("-e");
  commands.push_back(command);

  auto env = boost::this_process::environment();
  environment _env = env;
  // broken on windows env["JAVA_ARGS"] = "-Xmx1g -client";

  ipstream outStream;
  ipstream errStream;

  auto gfsh = executeChild(commands, _env, outStream, errStream);

  std::string line;

  while (outStream && std::getline(outStream, line)) {
    BOOST_LOG_TRIVIAL(trace) << "Gfsh::execute: " << line;
  }

  while (errStream && std::getline(errStream, line)) {
    BOOST_LOG_TRIVIAL(debug) << "Gfsh::execute: " << line;
  }

  gfsh.wait();

  auto exit_code = gfsh.exit_code();
  BOOST_LOG_TRIVIAL(debug) << "Gfsh::execute: exit:" << exit_code;

  if (exit_code) {
    throw new GfshExecuteException("gfsh error", exit_code);
  }
  extractConnectionCommand(command, user, password, keyStorePath, trustStorePath, keyStorePassword, trustStorePassword);
}

child GfshExecute::executeChild(std::vector<std::string> &commands,
                                environment &env, ipstream &outStream,
                                ipstream &errStream) {
#if defined(_WINDOWS)
  // https://github.com/klemens-morgenstern/boost-process/issues/159
  std::lock_guard<std::mutex> guard(g_child_mutex);
#endif
  return child(getFrameworkString(FrameworkVariable::GfShExecutable),
               args = commands, env, std_out > outStream, std_err > errStream);
}

void GfshExecute::extractConnectionCommand(const std::string &command, const std::string &user,
                                           const std::string &password, const std::string &keyStorePath,
                                           const std::string &trustStorePath, const std::string &keyStorePassword,
                                           const std::string &trustStorePassword) {
  if (starts_with(command, std::string("connect"))) {
    connection_ = command;
  } else if (starts_with(command, std::string("start locator"))) {
    auto jmxManagerHost = std::string("localhost");
    auto jmxManagerPort = std::string("1099");

    std::regex jmxManagerHostRegex("bind-address=([^\\s]+)");
    std::smatch jmxManagerHostMatch;
    if (std::regex_search(command, jmxManagerHostMatch, jmxManagerHostRegex)) {
      jmxManagerHost = jmxManagerHostMatch[1];
    }

    std::regex jmxManagerPortRegex("jmx-manager-port=(\\d+)");
    std::smatch jmxManagerPortMatch;
    if (std::regex_search(command, jmxManagerPortMatch, jmxManagerPortRegex)) {
      jmxManagerPort = jmxManagerPortMatch[1];
    }

    connection_ = "connect --jmx-manager=" + jmxManagerHost + "[" + jmxManagerPort + "]";

    if (!(user.empty() || password.empty())) {
      connection_ += " --user=" + user + " --password=" + password;
    }

    if(!(keyStorePath.empty() || trustStorePath.empty() || keyStorePassword.empty() || trustStorePassword.empty())) {
        connection_ += " --use-ssl=true --key-store=" + keyStorePath + " --trust-store=" + trustStorePath +
                " --key-store-password=" + keyStorePassword + " --trust-store-password=" + trustStorePassword;
    }
  }
}
