/**
 * 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 "Controller.h"

#include <utility>
#include <fstream>

#include "io/BufferStream.h"
#include "c2/C2Payload.h"
#include "io/AsioStream.h"
#include "asio/ssl/context.hpp"
#include "asio/ssl/stream.hpp"
#include "asio/connect.hpp"
#include "minifi-cpp/core/logging/Logger.h"
#include "utils/ConfigurationUtils.h"
#include "utils/net/AsioSocketUtils.h"
#include "utils/file/FileUtils.h"

namespace org::apache::nifi::minifi::controller {

bool sendSingleCommand(const utils::net::SocketData& socket_data, uint8_t op, const std::string& value) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  io::BufferStream buffer;
  buffer.write(&op, 1);
  buffer.write(value);
  return connection_stream->write(buffer.getBuffer()) == buffer.size();
}

bool stopComponent(const utils::net::SocketData& socket_data, const std::string& component) {
  return sendSingleCommand(socket_data, static_cast<uint8_t>(c2::Operation::stop), component);
}

bool startComponent(const utils::net::SocketData& socket_data, const std::string& component) {
  return sendSingleCommand(socket_data, static_cast<uint8_t>(c2::Operation::start), component);
}

bool clearConnection(const utils::net::SocketData& socket_data, const std::string& connection) {
  return sendSingleCommand(socket_data, static_cast<uint8_t>(c2::Operation::clear), connection);
}

bool updateFlow(const utils::net::SocketData& socket_data, std::ostream &out, const std::string& file) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  auto op = static_cast<uint8_t>(c2::Operation::update);
  io::BufferStream buffer;
  buffer.write(&op, 1);
  buffer.write("flow");
  buffer.write(file);
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return false;
  }
  // read the response
  uint8_t resp = 0;
  connection_stream->read(resp);
  if (resp == static_cast<uint8_t>(c2::Operation::describe)) {
    uint16_t connections = 0;
    connection_stream->read(connections);
    out << connections << " are full" << std::endl;
    for (uint16_t i = 0; i < connections; i++) {
      std::string fullcomponent;
      connection_stream->read(fullcomponent);
      out << fullcomponent << " is full" << std::endl;
    }
  }
  return true;
}

bool getFullConnections(const utils::net::SocketData& socket_data, std::ostream &out) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  auto op = static_cast<uint8_t>(c2::Operation::describe);
  io::BufferStream buffer;
  buffer.write(&op, 1);
  buffer.write("getfull");
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return false;
  }
  // read the response
  uint8_t resp = 0;
  connection_stream->read(resp);
  if (resp == static_cast<uint8_t>(c2::Operation::describe)) {
    uint16_t connections = 0;
    connection_stream->read(connections);
    out << connections << " are full" << std::endl;
    for (uint16_t i = 0; i < connections; i++) {
      std::string fullcomponent;
      connection_stream->read(fullcomponent);
      out << fullcomponent << " is full" << std::endl;
    }
  }
  return true;
}

bool getConnectionSize(const utils::net::SocketData& socket_data, std::ostream &out, const std::string& connection) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  auto op = static_cast<uint8_t>(c2::Operation::describe);
  io::BufferStream buffer;
  buffer.write(&op, 1);
  buffer.write("queue");
  buffer.write(connection);
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return false;
  }
  // read the response
  uint8_t resp = 0;
  connection_stream->read(resp);
  if (resp == static_cast<uint8_t>(c2::Operation::describe)) {
    std::string size;
    connection_stream->read(size);
    out << "Size/Max of " << connection << " " << size << std::endl;
  }
  return true;
}

bool listComponents(const utils::net::SocketData& socket_data, std::ostream &out, bool show_header) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  io::BufferStream buffer;
  auto op = static_cast<uint8_t>(c2::Operation::describe);
  buffer.write(&op, 1);
  buffer.write("components");
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return false;
  }
  uint16_t responses = 0;
  connection_stream->read(op);
  connection_stream->read(responses);
  if (show_header)
    out << "Components:" << std::endl;

  for (uint16_t i = 0; i < responses; i++) {
    std::string name;
    connection_stream->read(name, false);
    std::string status;
    connection_stream->read(status, false);
    out << name << ", running: " << status << std::endl;
  }
  return true;
}

bool listConnections(const utils::net::SocketData& socket_data, std::ostream &out, bool show_header) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  io::BufferStream buffer;
  auto op = static_cast<uint8_t>(c2::Operation::describe);
  buffer.write(&op, 1);
  buffer.write("connections");
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return false;
  }
  uint16_t responses = 0;
  connection_stream->read(op);
  connection_stream->read(responses);
  if (show_header)
    out << "Connection Names:" << std::endl;

  for (uint16_t i = 0; i < responses; i++) {
    std::string name;
    connection_stream->read(name, false);
    out << name << std::endl;
  }
  return true;
}

bool printManifest(const utils::net::SocketData& socket_data, std::ostream &out) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  io::BufferStream buffer;
  auto op = static_cast<uint8_t>(c2::Operation::describe);
  buffer.write(&op, 1);
  buffer.write("manifest");
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return false;
  }
  connection_stream->read(op);
  std::string manifest;
  connection_stream->read(manifest, true);
  out << manifest << std::endl;
  return true;
}

bool getJstacks(const utils::net::SocketData& socket_data, std::ostream &out) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  io::BufferStream buffer;
  auto op = static_cast<uint8_t>(c2::Operation::describe);
  buffer.write(&op, 1);
  buffer.write("jstack");
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return false;
  }
  connection_stream->read(op);
  std::string manifest;
  connection_stream->read(manifest, true);
  out << manifest << std::endl;
  return true;
}

std::expected<void, std::string> getDebugBundle(const utils::net::SocketData& socket_data, const std::filesystem::path& target_dir) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return std::unexpected{"Could not connect to remote host " + socket_data.host + ":" + std::to_string(socket_data.port)};
  }
  io::BufferStream buffer;
  auto op = static_cast<uint8_t>(c2::Operation::transfer);
  buffer.write(&op, 1);
  buffer.write("debug");
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return std::unexpected{"Could not write to connection " + socket_data.host + ":" + std::to_string(socket_data.port)};
  }
  connection_stream->read(op);
  size_t bundle_size = 0;
  connection_stream->read(bundle_size);
  if (bundle_size == 0) {
    return std::unexpected{"Failed to retrieve debug bundle"};
  }

  if (std::filesystem::exists(target_dir) && !std::filesystem::is_directory(target_dir)) {
    return std::unexpected{"Object specified as the target directory already exists and it is not a directory"};
  }

  if (!std::filesystem::exists(target_dir) && utils::file::create_dir(target_dir) != 0) {
    return std::unexpected{"Failed to create target directory: " + target_dir.string()};
  }

  std::ofstream out_file(target_dir / "debug.tar.gz");
  static constexpr auto BUFFER_SIZE = utils::configuration::DEFAULT_BUFFER_SIZE;
  std::array<char, BUFFER_SIZE> out_buffer{};
  while (bundle_size > 0) {
    const auto next_read_size = (std::min)(bundle_size, BUFFER_SIZE);
    const auto size_read = connection_stream->read(std::as_writable_bytes(std::span(out_buffer).subspan(0, next_read_size)));
    bundle_size -= size_read;
    out_file.write(out_buffer.data(), gsl::narrow<std::streamsize>(size_read));
  }
  return {};
}

bool getFlowStatus(const utils::net::SocketData& socket_data, const std::string& status_query, std::ostream &out) {
  const auto connection_stream = std::make_unique<utils::net::AsioSocketConnection>(socket_data);
  if (connection_stream->initialize() < 0) {
    return false;
  }
  io::BufferStream buffer;
  auto op = static_cast<uint8_t>(c2::Operation::describe);
  buffer.write(&op, 1);
  buffer.write("flowstatus");
  buffer.write(status_query);
  if (io::isError(connection_stream->write(buffer.getBuffer()))) {
    return false;
  }
  connection_stream->read(op);
  std::string manifest;
  connection_stream->read(manifest, true);
  out << manifest << std::endl;
  return true;
}

}  // namespace org::apache::nifi::minifi::controller
