// SPDX-FileComment: This file is part of TNL - Template Numerical Library (https://tnl-project.org/)
// SPDX-License-Identifier: MIT

#pragma once

#include <ostream>
#include <string>

#include <TNL/Config/ParameterContainer.h>

namespace TNL {

/// Creates calculations log in the form of a table.
class Logger
{
public:
   /**
    * \brief Basic constructor.
    *
    * \param width Integer that defines the width of the log.
    * \param stream Defines output stream where the log will be printed out.
    */
   Logger( int width, std::ostream& stream )
   : width( width ),
     stream( stream )
   {}

   /**
    * \brief Creates header in given log.
    *
    * The header usually contains title of the program.
    *
    * \param title A string containing the header title.
    */
   void
   writeHeader( const std::string& title );

   //! \brief Creates separator used as a log structure.
   void
   writeSeparator();

   /**
    * \brief Inserts information about various system parameters into the log.
    *
    * \param printGPUInfo When \e true, prints information about available GPUs.
    */
   bool
   writeSystemInformation( bool printGPUInfo = false );

   /**
    * \brief Inserts a line with current time into the log.
    *
    * \param label Label to be printed to the log together with the current time.
    */
   void
   writeCurrentTime( const char* label );

   /**
    * \brief Inserts parameter information into the log.
    *
    * \tparam ParameterType Type of the parameter.
    * \param label Description/label of the line.
    * \param parameterName Name of the parameter.
    * \param parameters A container with configuration parameters.
    * \param parameterLevel Integer defining the indent used in the log.
    */
   template< typename ParameterType >
   void
   writeParameter(
      const std::string& label,
      const std::string& parameterName,
      const Config::ParameterContainer& parameters,
      int parameterLevel = 0 );

   /**
    * \brief Inserts parameter information into the log.
    *
    * \tparam ParameterType Type of the parameter.
    * \param label Description/label of the line.
    * \param value Parameter value.
    * \param parameterLevel Integer defining the indent used in the log.
    */
   template< typename ParameterType >
   void
   writeParameter( const std::string& label, const ParameterType& value, int parameterLevel = 0 );

protected:
   //! \brief Integer defining the width of the log.
   int width;

   //! \brief Output stream where the log will be printed out.
   std::ostream& stream;
};

}  // namespace TNL

#include <TNL/Logger.hpp>
