// docker-finance | modern accounting for the power-user
//
// Copyright (C) 2021-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// 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 for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! \file
//! \author Aaron Fiore (Founder, Evergreen Crypto LLC)
//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter
//! \since docker-finance 1.1.0

#ifndef CONTAINER_SRC_ROOT_PLUGIN_COMMON_UTILITY_HH_
#define CONTAINER_SRC_ROOT_PLUGIN_COMMON_UTILITY_HH_

#include <initializer_list>
#include <string>

#include "../../common/utility.hh"

//! \namespace dfi
//! \since docker-finance 1.0.0
namespace dfi
{
//! \namespace dfi::plugin
//! \brief docker-finance plugins
//! \warning All plugins (repo/custom) must exist within this namespace
//!          and work within their own inner namespace
//! \since docker-finance 1.0.0
namespace plugin
{
//! \namespace dfi::plugin::common
//! \brief Shared ROOT plugin-related functionality
//! \since docker-finance 1.1.0
namespace common
{
//! \brief Load plugin by pseudo-paths
//! \details Wrapper to load from directory outside of default tree
//! \param path Must be of string "repo/file" or "custom/file" where file is
//!             a plugin filename that exists in repository plugin path or
//!             a client-side end-user's custom plugin path.
//! \ingroup cpp_plugin_impl
//! \details
//!   Example:
//!     <br>&emsp; root [0] dfi::plugin::load("repo/example.cc")<br>
//!
//!   Will load:
//!     <br>&emsp; ${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example.cc<br>
//!
//!   Example:
//!     <br>&emsp; root [0] dfi::plugin::load("custom/example.cc")<br>
//!
//!   Will load:
//!     <br>&emsp; ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example.cc<br>
//!
//! \note  Parent directory for all plugins are outside of repository's `root` directory
void load(const std::string& path)
{
  const std::string type{path.substr(0, path.find("/"))};

  std::string file{path};
  file.erase(0, file.find("/") + 1);

  if (type == "repo")
    {
      file.insert(
          0,
          ::dfi::common::get_env("DOCKER_FINANCE_CONTAINER_REPO")
              + "/plugins/root/");
    }
  else if (type == "custom")
    {
      file.insert(
          0,
          ::dfi::common::get_env("DOCKER_FINANCE_CONTAINER_PLUGINS")
              + "/root/");
    }
  else
    {
      ::dfi::common::throw_ex<::dfi::common::type::RuntimeError>(
          "must be of type 'repo/<file>' or 'custom/<file>'");
    }

  ::dfi::common::Command::load(file);
}

//! \brief Wrapper to load plugins by list of pseudo-paths
//! \ingroup cpp_plugin_impl
//! \param paths List must consist of string "repo/file" or "custom/file" where file is
//!              a plugin filename that exists in repository plugin path or
//!              a client-side end-user's custom plugin path.
//! \details
//!   Example:
//!     <br>&emsp; root [0] dfi::plugin::load({"repo/example.cc", "custom/example.cc"})<br>
//!
//!   Will load:
//!     <br>&emsp; ${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/example.cc
//!                and ${DOCKER_FINANCE_CLIENT_PLUGINS}/root/example.cc<br>
//!
//! \note  Parent directory for all plugins are outside of repository's `root` directory
void load(const std::initializer_list<std::string>& paths)
{
  for (const auto& path : paths)
    ::dfi::plugin::common::load(path);
}
}  // namespace common

//! \brief Convenience wrapper to inner common loader
//! \ingroup cpp_plugin
//! \since docker-finance 1.1.0
void load(const std::string& path)
{
  common::load(path);
}
//! \brief Convenience wrapper to inner common loader
//! \ingroup cpp_plugin
//! \since docker-finance 1.1.0
void load(const std::initializer_list<std::string>& paths)
{
  common::load(paths);
}

// TODO(afiore): unload

}  // namespace plugin
}  // namespace dfi

#endif  // CONTAINER_SRC_ROOT_PLUGIN_COMMON_UTILITY_HH_

// # vim: sw=2 sts=2 si ai et
