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

#include "minifi-cpp/utils/gsl.h"

#include "core/logging/LoggerConfiguration.h"
#include "core/logging/LoggerFactory.h"
#include "utils/StringUtils.h"
#include "properties/Configuration.h"

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

bool ConfigureImpl::get(const std::string& key, std::string& value) const {
  if (auto opt_value = getRawValue(key)) {
    value = *opt_value;
    if (decryptor_ && isEncrypted(key)) {
      value = decryptor_->decrypt(value);
    }
    return true;
  }
  return false;
}

bool ConfigureImpl::get(const std::string& key, const std::string& alternate_key, std::string& value) const {
  if (get(key, value)) {
    if (get(alternate_key)) {
      const auto logger = core::logging::LoggerFactory<Configure>::getLogger();
      logger->log_warn("Both the property '{}' and an alternate property '{}' are set. Using '{}'.", key, alternate_key, key);
    }
    return true;
  } else if (get(alternate_key, value)) {
    const auto logger = core::logging::LoggerFactory<Configure>::getLogger();
    logger->log_warn("{} is an alternate property that may not be supported in future releases. Please use {} instead.", alternate_key, key);
    return true;
  } else {
    return false;
  }
}

std::optional<std::string> ConfigureImpl::get(const std::string& key) const {
  std::string value;
  if (get(key, value)) {
    return value;
  }
  return std::nullopt;
}

std::optional<std::string> ConfigureImpl::getWithFallback(const std::string& key, const std::string& alternate_key) const {
  std::string value;
  if (get(key, alternate_key, value)) {
    return value;
  }
  return std::nullopt;
}

std::optional<std::string> ConfigureImpl::getRawValue(const std::string& key) const {
  static constexpr std::string_view log_prefix = "nifi.log.";
  if (utils::string::startsWith(key, log_prefix)) {
    if (logger_properties_) {
      return logger_properties_->getString(key.substr(log_prefix.length()));
    }
    return std::nullopt;
  }

  return getString(key);
}

bool ConfigureImpl::isEncrypted(const std::string& key) const {
  gsl_Expects(decryptor_);
  const auto encryption_marker = getString(key + ".protected");
  return decryptor_->isValidEncryptionMarker(encryption_marker);
}

std::optional<std::string> ConfigureImpl::getAgentClass() const {
  std::string agent_class;
  if (get(Configuration::nifi_c2_agent_class, "c2.agent.class", agent_class) && !agent_class.empty()) {
    return agent_class;
  }
  return {};
}

std::string ConfigureImpl::getAgentIdentifier() const {
  std::string agent_id;
  if (!get(Configuration::nifi_c2_agent_identifier, "c2.agent.identifier", agent_id) || agent_id.empty()) {
    std::lock_guard<std::mutex> guard(fallback_identifier_mutex_);
    return fallback_identifier_;
  }
  return agent_id;
}

void ConfigureImpl::setFallbackAgentIdentifier(const std::string& id) {
  std::lock_guard<std::mutex> guard(fallback_identifier_mutex_);
  fallback_identifier_ = id;
}

std::optional<std::filesystem::path> ConfigureImpl::logPropertiesFilePath() const {
  if (logger_properties_) {
    return logger_properties_->getFilePath();
  }
  return std::nullopt;
}

std::optional<std::filesystem::path> ConfigureImpl::extraLogPropertiesFilesDirName() const {
  if (logger_properties_) {
    return logger_properties_->extraPropertiesFilesDirName();
  }
  return std::nullopt;
}

void ConfigureImpl::set(const std::string& key, const std::string& value, PropertyChangeLifetime lifetime) {
  const std::string_view log_prefix = "nifi.log.";
  if (utils::string::startsWith(key, log_prefix)) {
    if (logger_properties_) {
      logger_properties_changed_ = true;
      logger_properties_->set(key.substr(log_prefix.length()), value, lifetime);
    }
  } else {
    ConfigurationImpl::set(key, value, lifetime);
  }
}

bool ConfigureImpl::commitChanges() {
  bool success = true;
  if (logger_properties_) {
    success &= logger_properties_->commitChanges();
    if (logger_properties_changed_) {
      core::logging::LoggerConfiguration::getConfiguration().initialize(logger_properties_);
      logger_properties_changed_ = false;
    }
  }
  success &= ConfigurationImpl::commitChanges();
  return success;
}

gsl::not_null<std::shared_ptr<Configure>> Configure::create() {
  return gsl::make_not_null<std::shared_ptr<Configure>>(std::make_shared<ConfigureImpl>());
}

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