/**
 *
 * 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 "properties/Properties.h"
#include <string>
#include "utils/StringUtils.h"
#include "utils/file/FileUtils.h"
#include "utils/file/PathUtils.h"
#include "core/Core.h"
#include "core/logging/LoggerConfiguration.h"

namespace org {
namespace apache {
namespace nifi {
namespace minifi {

#define TRACE_BUFFER_SIZE 512

Properties::Properties(const std::string& name)
    : logger_(logging::LoggerFactory<Properties>::getLogger()),
    name_(name) {
}

// Get the config value
bool Properties::getString(const std::string &key, std::string &value) const {
  std::lock_guard<std::mutex> lock(mutex_);
  auto it = properties_.find(key);

  if (it != properties_.end()) {
    value = it->second;
    return true;
  } else {
    return false;
  }
}

int Properties::getInt(const std::string &key, int default_value) const {
  std::lock_guard<std::mutex> lock(mutex_);
  auto it = properties_.find(key);

  return it != properties_.end() ? std::stoi(it->second) : default_value;
}

// Parse one line in configure file like key=value
bool Properties::parseConfigureFileLine(char *buf, std::string &prop_key, std::string &prop_value) {
  char *line = buf;

  while ((line[0] == ' ') || (line[0] == '\t'))
    ++line;

  char first = line[0];
  if ((first == '\0') || (first == '#') || (first == '[')  || (first == '\r') || (first == '\n') || (first == '=')) {
    return true;
  }

  char *equal = strchr(line, '=');
  if (equal == NULL) {
    return false;  // invalid property as this is not a comment or property line
  }

  equal[0] = '\0';
  std::string key = line;

  equal++;
  while ((equal[0] == ' ') || (equal[0] == '\t'))
    ++equal;

  first = equal[0];
  if ((first == '\0') || (first == '\r') || (first == '\n')) {
    return true;  // empty properties are okay
  }

  std::string value = equal;
  value = org::apache::nifi::minifi::utils::StringUtils::replaceEnvironmentVariables(value);
  prop_key = org::apache::nifi::minifi::utils::StringUtils::trimRight(key);
  prop_value = org::apache::nifi::minifi::utils::StringUtils::trimRight(value);
  return true;
}

// Load Configure File
void Properties::loadConfigureFile(const char *fileName) {
  if (NULL == fileName) {
    logger_->log_error("Configuration file path for %s is a nullptr!", getName().c_str());
    return;
  }

  properties_file_ = utils::file::getFullPath(utils::file::FileUtils::concat_path(getHome(), fileName));

  logger_->log_info("Using configuration file to load configuration for %s from %s (located at %s)", getName().c_str(), fileName, properties_file_);

  std::ifstream file(properties_file_, std::ifstream::in);
  if (!file.good()) {
    logger_->log_error("load configure file failed %s", properties_file_);
    return;
  }
  this->clear();

  char buf[TRACE_BUFFER_SIZE];
  for (file.getline(buf, TRACE_BUFFER_SIZE); file.good(); file.getline(buf, TRACE_BUFFER_SIZE)) {
    std::string key, value;
    if (parseConfigureFileLine(buf, key, value)) {
      set(key, value);
    }
  }
  dirty_ = false;
}

bool Properties::validateConfigurationFile(const std::string &configFile) {
  std::ifstream file(configFile, std::ifstream::in);
  if (!file.good()) {
    logger_->log_error("Failed to load configuration file %s to configure %s", configFile, getName().c_str());
    return false;
  }

  char buf[TRACE_BUFFER_SIZE];
  for (file.getline(buf, TRACE_BUFFER_SIZE); file.good(); file.getline(buf, TRACE_BUFFER_SIZE)) {
    std::string key, value;
    if (!parseConfigureFileLine(buf, key, value)) {
      logger_->log_error("While loading configuration for %s found invalid line: %s", getName().c_str(), buf);
      return false;
    }
  }
  return true;
}

bool Properties::persistProperties() {
  std::lock_guard<std::mutex> lock(mutex_);
  if (!dirty_) {
    logger_->log_info("Attempt to persist, but properties are not updated");
    return true;
  }
  std::ifstream file(properties_file_, std::ifstream::in);
  if (!file.good()) {
    logger_->log_error("load configure file failed %s", properties_file_);
    return false;
  }

  std::map<std::string, std::string> properties_copy = properties_;

  std::string new_file = properties_file_ + ".new";

  std::ofstream output_file(new_file, std::ios::out);

  char buf[TRACE_BUFFER_SIZE];
  for (file.getline(buf, TRACE_BUFFER_SIZE); file.good(); file.getline(buf, TRACE_BUFFER_SIZE)) {
    char *line = buf;

    char first = line[0];

    if ((first == '\0') || (first == '#') || (first == '[') || (first == '\r') || (first == '\n') || (first == '=')) {
      // persist comments and newlines
      output_file << line << std::endl;
      continue;
    }



    char *equal = strchr(line, '=');
    if (equal == NULL) {
      output_file << line << std::endl;
      continue;
    }

    equal[0] = '\0';
    std::string key = line;

    equal++;
    while ((equal[0] == ' ') || (equal[0] == '\t'))
      ++equal;

    first = equal[0];
    if ((first == '\0') || (first == '\r') || (first == '\n')) {
      output_file << line << std::endl;
      continue;
    }

    key = org::apache::nifi::minifi::utils::StringUtils::trimRight(key);
    std::string value = org::apache::nifi::minifi::utils::StringUtils::trimRight(equal);
    auto hasIt = properties_copy.find(key);
    if (hasIt != properties_copy.end() && !value.empty()) {
      output_file << key << "=" << value << std::endl;
    }
    properties_copy.erase(key);
  }

  for (const auto &kv : properties_copy) {
    if (!kv.first.empty() && !kv.second.empty())
      output_file << kv.first << "=" << kv.second << std::endl;
  }
  output_file.close();

  if (validateConfigurationFile(new_file)) {
    const std::string backup = properties_file_ + ".bak";
    if (!utils::file::FileUtils::copy_file(properties_file_, backup) && !utils::file::FileUtils::copy_file(new_file, properties_file_)) {
      logger_->log_info("Persisted %s", properties_file_);
      return true;
    } else {
      logger_->log_error("Could not update %s", properties_file_);
    }
  }

  dirty_ = false;

  return false;
}

// Parse Command Line
void Properties::parseCommandLine(int argc, char **argv) {
  int i;
  bool keyFound = false;
  std::string key, value;

  for (i = 1; i < argc; i++) {
    if (argv[i][0] == '-' && argv[i][1] != '\0') {
      keyFound = true;
      key = &argv[i][1];
      continue;
    }
    if (keyFound) {
      value = argv[i];
      set(key, value);
      keyFound = false;
    }
  }
  return;
}

} /* namespace minifi */
} /* namespace nifi */
} /* namespace apache */
} /* namespace org */
