 /********************************************************************************
 * Copyright (c) 2025-2026 ZF Friedrichshafen AG
 *
 * This program and the accompanying materials are made available under the 
 * terms of the Apache License Version 2.0 which is available at
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * SPDX-License-Identifier: Apache-2.0 
 *
 * Contributors:
 *   Erik Verhoeven - initial API and implementation
 ********************************************************************************/

#include "core.idl"

/**
 * @brief Software Defined Vehicle framework.
 */
module sdv
{
    /**
     * @brief TOML interface.
     */
    module toml
    {
        /**
         * @brief TOML parse exception.
         */
        exception XTOMLParseException : XSysExcept
        {
            /** Description */
            const char _description[] = "TOML parse exception.";

            u8string ssMessage;     ///< Message indicating the cause of the exception.
        };

        /**
         * @brief Collection of possible data in parse tree node
         */
        enum ENodeType : uint32
        {
            node_table,	            ///< Table
            node_array,	            ///< Array
            node_integer,           ///< Integer
            node_floating_point,    ///< Floating point
            node_boolean,           ///< Boolean
            node_string,            ///< String
            node_invalid            ///< Invalid content
        };

        /**
         * @brief The indicator of an invalid position used in various functions using indices.
         */
        const uint32 npos = 0xFFFFFFFF;

        /**
         * @brief Node information interface
         */
        interface INodeInfo
        {
            /**
             * @brief Get the node name (no conversion to a literal or quoted key is made).
             * @return String containing the name of the node.
             */
            u8string GetName() const;

            /**
             * @brief Get the node path following the key rules for bar, literal and quoted keys.
             * @param[in] bResolveArrays When set, include array indices in the path. The path returned without array indices is
             * identical to the code in the TOML file. The path returned with array indices is identical to the direct access of
             * nodes within the parser.
             * @return String containing the path of the node.
             */
            u8string GetPath(in boolean bResolveArrays) const;

            /**
             * @brief Get the node type.
             * @return Type of the node.
             */
            ENodeType GetType() const;

            /**
             * @brief The node value.
             * @return For boolean, integer, floating point and strings, the function returns a value. Otherwise the function
             * returns empty.
             */
            any GetValue() const;

            /**
             * @brief Get the index of this node within the parent collection.
             * @return The index of the node within the parent collection node or npos when no parent is available.
             */
            uint32 GetIndex() const;

            /**
             * @brief Get the parent collection node.
             * @return Returns the parent collection node or NULL when there is no parent collection node.
             */
            IInterfaceAccess GetParent() const;

            /**
             * @brief Return the TOML string belonging to this node including all potential child nodes and comments.
             * @return The TOML string.
             */
            u8string GetTOML() const;

            /**
             * @brief Node comment type.
             */
            enum ECommentType
            {
                comment_before = 0,                 ///< The comment before the node. This will insert a newline and the comment
                                                    ///< text preceded by the '#' character.
                comment_behind = 1,                 ///< The comment behind the node. This will align the comment to te next tab
                                                    ///< stop and precedes the comment with the '#' character.
                out_of_scope_comment_before = 2,    ///< An independent comment before the node. This comment is not part of the
                                                    ///< node and is separated by an extra newline.
                out_of_scope_comment_behind = 3,    ///< An independent comment behind the node. This comment is not part of the
                                                    ///< node and is separated by an extra newline.
            };

            /**
             * @brief Set or replace a comment for the node.
             * @details Set the comment text for the node. If a comment is provided as text (normal behavior), the comment text will
             * be formatted automatically when generating the TOML text. If the comment text should not contain the comment
             * character '#' before the comment text.
             * Comments inserted before the node will be inserted on the line before the node unless the comment is provided in raw
             * format and is ended with a line-break and optionally whitespace. Comment inserted behind the node will be inserted on
             * the same line as the node.
             * Comments provided as text is automatically wrapped to 132 characters if possible. Line-breaks in the text will cause
             * a new comment line to start.
             * @param[in] eType The comment type to set the comment text for.
             * @param[in] ssComment String containing the comment text to set.
             */
            void SetComment(in ECommentType eType, in u8string ssComment);

            /**
             * Get the current comment for the node.
             * @param[in] eType The comment type to get the comment text of.
             * @return String with the comment text or an empty string if no comment is available.
             */
            u8string GetComment(in ECommentType eType);

            /**
             * @brief Format the node automatically, remove redundant whitespace.
             * @param[in] bRemoveComments When set, the comments are removed from the node.
             */
            void AutomaticFormat(in boolean bRemoveComments);

            /**
             * @brief Is the node inline?
             * @return Returns whether the node is defined as inline node.
             */
            boolean IsInline() const;

            /**
             * @brief Is the node defined as standard node?
             * @return Returns whether the node is defined as standard node.
             */
            boolean IsStandard() const;
        };

        /**
         * @brief Update the current node.
         * @remarks The root node cannot be updated.
         */
        interface INodeUpdate
        {
            /**
             * @brief Change the key name of the node (if the node is not a value node of an array).
             * @param[in] ssNewName The name to assign to the node. The name must adhere to the key names defined by the TOML
             * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
             * parser decides itself whether the key is bare-key, a literal key or a quoted key.
             * @return Returns whether the name change was successful.
             */
            boolean ChangeName(in u8string ssNewName);

            /**
             * @brief Change the value of the node.
             * @remarks Only valid for value nodes. Changing the value type is not supported.
             * @param[in] anyNewValue The value of the node, being either an integer, floating point number, boolean value or a
             * string. Conversion is automatically done to int64, double float, bool or u8string.
             * @return Returns whether the value change was successful.
             */
            boolean ChangeValue(in any anyNewValue);

            /**
             * @brief Move up the node in the collection.
             * @remarks External tables or table arrays cannot be moved before value nodes.
             * @remarks Moving if the node is the first node is not possible.
             * @return Returns whether the move was successful.
             */
            boolean MoveUp();

            /**
             * @brief Move down the node in the collection.
             * @remarks Value nodes cannot be moved behind external tables or table arrays.
             * @remarks Moving if the node is the last node is not possible.
             * @return Returns whether the move was successful.
             */
            boolean MoveDown();

            /**
             * @brief Delete the current node.
             * @attention A successful deletion will cause all interfaces to the current node to become inoperable.
             * @return Returns whether the deletion was successful.
             */
            boolean DeleteNode();
        };

        /**
         * @brief Interface allowing access to table and array nodes.
         */
        interface INodeCollection
        {
            /**
             * @brief Returns the amount of nodes.
             * @return The amount of nodes.
            */
            uint32 GetCount() const;

            /**
             * @brief Get the node.
             * @param[in] uiIndex Index of the node to get.
             * @return Interface to the node object.
             */
            IInterfaceAccess GetNode(in uint32 uiIndex) const;

            /**
             * @brief Searches a node by its key in the parse tree
             * @details Elements of tables can be accessed and traversed by using '.' to separated the parent name from child
             * name. E.g. 'parent.child' would access the 'child' element of the 'parent' table. Elements of arrays can be
             * accessed and traversed by using the index number in brackets. E.g. 'array[3]' would access the fourth element of
             * the array 'array'. These access conventions can also be chained like 'table.array[2][1].subtable.integerElement'.
             * @attention Array indexing starts with 0!
             * @param[in] ssPath The path of the Node to searched for.
             * @return Returns an interface the requested node if available.
             */
            IInterfaceAccess GetNodeDirect(in u8string ssPath) const;
        };

        /**
         * @brief Convert between inline and standard definitions.
         */
        interface INodeCollectionConvert
        {
            /**
             * @brief Can the node convert to an inline definition?
             * @return Returns whether the conversion to inline is possible. Returns 'true' when the node is already inline.
             */
            boolean CanMakeInline() const;

            /**
             * @brief Convert the node to an inline node.
             * @return Returns whether the conversion was successful. Returns 'true' when the node was already inline.
             */
            boolean MakeInline();

            /**
             * @brief Can the node convert to a standard definition?
             * @return Returns whether the conversion to standard is possible. Returns 'true' when the node is already defined as
             * standard node.
             */
            boolean CanMakeStandard() const;

            /**
             * @brief Convert the node to a standard node.
             * @param[in] bIncludeChildren When set, applicable child nodes are made are converted to standard nodes as well (only
             * tables and table-arrays can be defined as standard).
             * @return Returns whether the conversion was successful. Returns 'true' when the node was already defined as standard
             * node.
             */
            boolean MakeStandard(in boolean bIncludeChildren);
        };

        /**
         * @brief Insertion preference for tables and table arrays, being standard or inline.
         */
        enum EInsertPreference
        {
            prefer_standard = 0, ///< When the parent node is not inline, the node will be inserted as standard node.
            prefer_inline   = 1, ///< The node will be inserted as inline node.
        };

        /**
         * @brief Extend the collection node with values, arrays and tables.
         */
        interface INodeCollectionInsert
        {
            /**
             * @brief Insert a value into the collection at the location before the supplied index.
             * @remarks In TOML, inline nodes are located before standard nodes. Since values are presented as inline node, they
             * will be inserted before any standard node (table or table array if defined as standard node).
             * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
             * square brackets. Can be empty, causing the node to be inserted at the end.
             * @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
             * not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
             * string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
             * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
             * parser decides itself whether the key is bare-key, a literal key or a quoted key.
             * @param[in] anyValue The value of the node, being either an integer, floating point number, boolean value or a string.
             * Conversion is automatically done to int64, double float, bool or u8string.
             * @return On success the interface to the newly inserted node is returned or NULL otherwise.
             */
            IInterfaceAccess InsertValue(in u8string ssInsertBefore, in u8string ssName, in any anyValue);

            /**
             * @brief Insert an array into the collection at the location before the supplied index.
             * @remarks In TOML, inline nodes are located before standard nodes. Since arrays are presented as inline node, they
             * will be inserted before any standard node (table or table array if defined as standard node).
             * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
             * square brackets. Can be empty, causing the node to be inserted at the end.
             * @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
             * not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
             * string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
             * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
             * parser decides itself whether the key is bare-key, a literal key or a quoted key.
             * @return On success the interface to the newly inserted node is returned or NULL otherwise.
             */
            IInterfaceAccess InsertArray(in u8string ssInsertBefore, in u8string ssName);

            /**
             * @brief Insert a table into the collection at the location before the supplied index.
             * @remarks In TOML, inline nodes are located before standard nodes. Tables can be inserted as inline node, in which
             * case they will be inserted before any standard node (table or table array if defined as standard node).
             * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
             * square brackets. Can be empty, causing the node to be inserted at the end.
             * @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
             * not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
             * string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
             * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
             * parser decides itself whether the key is bare-key, a literal key or a quoted key.
             * @param[in] ePreference The preferred form of the node to be inserted.
             * @return On success the interface to the newly inserted node is returned or NULL otherwise.
             */
            IInterfaceAccess InsertTable(in u8string ssInsertBefore, in u8string ssName, in EInsertPreference ePreference);

            /**
             * @brief Insert a table array into the collection at the location before the supplied index.
             * @remarks In TOML, inline nodes are located before standard nodes. Table arrays can be inserted as inline node, in
             * which case they will be inserted before any standard node (table or table array if defined as standard node).
             * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
             * square brackets. Can be empty, causing the node to be inserted at the end.
             * @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
             * not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
             * string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
             * specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
             * parser decides itself whether the key is bare-key, a literal key or a quoted key.
             * @param[in] ePreference The preferred form of the node to be inserted.
             * @return On success the interface to the newly inserted node is returned or NULL otherwise.
             */
            IInterfaceAccess InsertTableArray(in u8string ssInsertBefore, in u8string ssName, in EInsertPreference ePreference);

            /**
             * @brief The result of the TOML string to insert.
             */
            enum EInsertResult : uint32
            {
                insert_fail,            ///< The TOML string was invalid or didn't fit the collection node it was to be inserted.
                insert_partly_success,  ///< Part, but not all nodes could be inserted (duplicate nodes are not inserted).
                insert_success,         ///< All nodes could be inserted or the TOML didn't contain any nodes.
            };

            /**
             * @brief Insert a TOML string as a child of the current collection node. If the collection is a table, the TOML string
             * should contain values and inline/external/array-table nodes with names. If the collection is an array, the TOML
             * string should contain and inline table nodes without names.
             * @remarks In TOML, inline nodes are located before standard nodes. Dependable on the nodes defined in the TOML they
             * might be transferred to inline or they might be inserted at a different location.
             * @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
             * square brackets. Can be empty, causing the node to be inserted at the end.
             * @param[in] ssTOML The TOML string to insert. This string can hold one or more nodes that should be inserted.
             * @param[in] bRollbackOnFailure If only part of the nodes could be inserted, no node will be inserted.
             * @return The result of the insertion.
             */
            EInsertResult InsertTOML(in u8string ssInsertBefore, in u8string ssTOML, in boolean bRollbackOnFailure);
        };

        /**
         * @brief TOML parser interface.
         */
        interface ITOMLParser
        {
            /**
             * @brief Process the configuration from the supplied content string.
             * @param[in] ssContent Configuration string.
             * @return Returns 'true' when the configuration could be read successfully, false when not.
             */
            boolean Process(in u8string ssContent) raises(XTOMLParseException);
        };
    };
};