//
// LDASTools frameCPP - A library implementing the LIGO/Virgo frame
// specification
//
// Copyright (C) 2025 California Institute of Technology
//
// LDASTools frameCPP is free software; you may redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 (GPLv2) of the
// License or at your discretion, any later version.
//
// LDASTools frameCPP is distributed in the hope that it will be useful, but
// without any warranty or even the implied warranty of merchantability
// or fitness for a particular purpose. See the GNU General Public
// License (GPLv2) for more details.
//
// Neither the names of the California Institute of Technology (Caltech),
// The Massachusetts Institute of Technology (M.I.T), The Laser
// Interferometer Gravitational-Wave Observatory (LIGO), nor the names
// of its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// You should have received a copy of the licensing terms for this
// software included in the file LICENSE located in the top-level
// directory of this package. If you did not, you can view a copy at
// http://dcc.ligo.org/M1500244/LICENSE
//

#ifndef FRAMECPP_DYNAMIC_TOC_PRINTER_HH
#define FRAMECPP_DYNAMIC_TOC_PRINTER_HH

#include <iostream>
#include <functional>
#include <map>
#include "framecpp/Universal/FrTOC.hh"
#include "framecpp/Common/Description.hh"

namespace FrameCPP
{
    namespace Test
    {
        /**
         * @brief Metadata-driven TOC printer that uses Description system (v8+ only)
         *
         * Unlike LegacyTOCPrinter and ModernTOCPrinter which have hardcoded
         * field names and expectations, DynamicTOCPrinter reads the FrSH/FrSE
         * metadata from the file to determine what fields exist and how to
         * print them.
         *
         * IMPORTANT: This only works for v8+ frame files because the FrSE
         * entries in those versions contain complete type information. For v<8,
         * use LegacyTOCPrinter instead.
         */
        class DynamicTOCPrinter
        {
        public:
            using FieldPrinter = std::function<void(const Universal::FrTOC*, std::ostream&)>;

            explicit DynamicTOCPrinter( std::ostream& os );

            /**
             * @brief Print TOC using metadata from Description system
             * @param toc The TOC object to print
             * @param desc Description containing FrSH/FrSE metadata from file
             *
             * @note Version information is embedded in the Description itself,
             *       so no separate version parameter is needed.
             */
            void print( const Universal::FrTOC* toc, const Common::Description& desc );

            /**
             * @brief Get access to field printer registry
             * @return Reference to field printer map
             */
            const std::map<std::string, FieldPrinter>& GetFieldPrinters() const { return m_field_printers; }

            /**
             * @brief Set maximum elements to display in arrays
             * @param max_elements Maximum elements to show (0 = show all)
             */
            void SetMaxArrayDisplay(size_t max_elements) { m_max_array_display = max_elements; }

            /**
             * @brief Get current max array display setting
             * @return Maximum elements to display (0 = show all)
             */
            size_t GetMaxArrayDisplay() const { return m_max_array_display; }

        private:
            std::ostream& m_os;
            std::map<std::string, FieldPrinter> m_field_printers;
            size_t m_max_array_display;

            void initializeFieldPrinters();
        };

    } // namespace Test
} // namespace FrameCPP

#endif // FRAMECPP_DYNAMIC_TOC_PRINTER_HH
