/*
 * Copyright (c) 2021, 2023, Oracle and/or its affiliates.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2.0,
 * as published by the Free Software Foundation.
 *
 * This program is also distributed with certain software (including
 * but not limited to OpenSSL) that is licensed under separate terms, as
 * designated in a particular file or component or in included license
 * documentation.  The authors of MySQL hereby grant you an additional
 * permission to link the program and your derivative works with the
 * separately licensed software that they have included with MySQL.
 * This program is distributed in the hope that it will be useful,  but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 * the GNU General Public License, version 2.0, for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "mysqlshdk/libs/storage/backend/oci_par_directory.h"

#include <memory>
#include <unordered_set>
#include <utility>

#include "mysqlshdk/libs/db/uri_encoder.h"
#include "mysqlshdk/libs/utils/utils_general.h"

namespace mysqlshdk {
namespace storage {
namespace backend {
namespace oci {

using mysqlshdk::db::uri::pctencode_query_value;

Oci_par_directory::Oci_par_directory(const Oci_par_directory_config_ptr &config)
    : Http_directory(config, true), m_config(config) {
  init_rest();
}

Masked_string Oci_par_directory::full_path() const {
  return ::mysqlshdk::oci::anonymize_par(m_config->par().full_url());
}

std::string Oci_par_directory::get_list_url() const {
  // use delimiter to limit the number of results, we're just interested in the
  // files in the current directory
  std::string url = "?fields=name,size&delimiter=/";

  if (!m_config->par().object_prefix().empty()) {
    url += "&prefix=" + pctencode_query_value(m_config->par().object_prefix());
  }

  if (!m_next_start_with.empty()) {
    url += "&start=" + pctencode_query_value(m_next_start_with);
  }

  return url;
}

std::unordered_set<IDirectory::File_info> Oci_par_directory::parse_file_list(
    const std::string &data, const std::string &pattern) const {
  std::unordered_set<IDirectory::File_info> list;

  const auto response = shcore::Value::parse(data.data(), data.size()).as_map();
  const auto objects = response->get_array("objects");
  m_next_start_with = response->get_string("nextStartWith", "");
  const auto prefix_length = m_config->par().object_prefix().length();

  list.reserve(objects->size());

  for (const auto &object : *objects) {
    const auto file = object.as_map();
    auto name = file->get_string("name").substr(prefix_length);

    if (pattern.empty() || shcore::match_glob(pattern, name)) {
      list.emplace(std::move(name),
                   static_cast<size_t>(file->get_uint("size")));
    }
  }

  return list;
}

bool Oci_par_directory::is_list_files_complete() const {
  return m_next_start_with.empty();
}

void Oci_par_directory::init_rest() {
  Http_directory::init_rest(
      ::mysqlshdk::oci::anonymize_par(m_config->par().par_url()));
}

}  // namespace oci
}  // namespace backend
}  // namespace storage
}  // namespace mysqlshdk
