#ifndef SCPI_TREE_LIST_EXTENTION_H
#define SCPI_TREE_LIST_EXTENTION_H
   #include "app/tlst/tree_list.h"   
   #include "app/scpi/scpi_core.h"

   // Author: Sychov A., Jan 2021
   // Extension module to adopt the Tree-List algorithms to the SCPI module.

   //----------------------------------------------------------------
   // Refer to:
   // [1] IEEE 488.2 Standard, revision IEEE Std 488.2-1987 (1992)
   //     "IEEE Standard Codes, Formats, Protocols, and Common Commands for Use With IEEE Std 488.1-1987, IEEE
   //      Standard Digital Interface for Programmable Instrumentation"
   // [2] SCPI Specification, revision 1999.0
   //     "Standard Commands for Programmable Instruments (SCPI), VERSION 1999.0, May 1999"
   //----------------------------------------------------------------

   // ========================================================================================================
   // @scpi_command_header_compare
   // Compares the program mnemonic of registered command (@command) with
   // ... the program mnemonic of received command header (@src_key).
   // Function ignores the tailing question mark of the command header mnemonic.
   // References:
   //  "7.6 Program Header Functional Elements", [1]
   // @commandString - the registered command header part, null-term string,
   // ... attached to the node using @nodekey_ parameter of DECLARE_TREE_LIST_LEAF.
   // @comparingToken - the searching command header part, a pair of (@shead, @stail)
   // ... pointers grouped into the @sStrToken_t.
   // Note: the @sStrToken_t structure referred by @src_key shall be writable.
   // Note: @command can points to the part of the original command string.
   // Returns: The function returns true in case the part specified by @src_key 
   // ... matchs to the part of the command specified by @command and nearest  
   // ... mnemonic separator (colon).
   bool scpi_command_header_compare( const char * commandString,
                                     const sStrToken_t * comparingToken );

   // @treelist_header_compare
   // Function-wrapper for Tree-List.
   // Compares the program mnemonic of registered command (@command) with
   // ... the program mnemonic of received command header (@src_key).
   // @v_command = @commandString (@scpi_command_header_compare)
   // @v_src_key = @comparingToken (@scpi_command_header_compare)
   // Refer: @command_header_compare for details.
   static inline bool treelist_header_compare( const void * v_command,
                                               const void * v_src_key )
   {
       return scpi_command_header_compare( (const char*)v_command, (const sStrToken_t*)v_src_key );
   }
   // ========================================================================================================
   // @scpi_is_default_node
   // Checks if the passed string is the default (optional) SCPI command mnemonic
   // Is used to determine the default node in the tree-list.
   // References:
   //  "5.1 Interpreting Command Tables", [2]
   //  "7.6.1 <COMMAND PROGPRAM HEADER>", [1]
   //  "7.6.1.5 Header Compounding Rules", [1]
   // @commandString - SCPI command simple mnemonic;
   // Note: compound mnemonics are not supported;
   // Note: the passed mnemonic must be valid, the mnemonic will not be validated.
   // Returns:
   // - true: the specified @commandString is the default command mnemonic;
   // - false: the specified @commandString is not the default command mnemonic;
   bool scpi_is_default_node( const char * commandString );

   // @treelist_is_default_node
   // Function-wrapper for Tree-List.
   // Checks if the passed string is the default (optional) SCPI command mnemonic
   // Is used to determine the default node in the tree-list.
   // @node - node to check;
   // @ctx - optional user dependent context, can be NULL;
   // References:
   //  "5.1 Interpreting Command Tables", [2]
   //  "7.6.1 <COMMAND PROGPRAM HEADER>", [1]
   //  "7.6.1.5 Header Compounding Rules", [1]
   // Returns:
   // - true: the specified @node is the default node;
   // - false: the specified @node is not the default node;
   // Note: compound mnemonics are not supported;
   // Note: the passed mnemonic must be valid, the mnemonic will not be validated.
   static inline bool treelist_is_default_node( const sTreeList_t * node, void * ctx )
   {
       return scpi_is_default_node( node->c_key );
   }

   // ========================================================================================================
   #if TREE_LIST_RECURSIVE_LIMIT_ENABLE
   // @scpi_search_recursive_limiter   
   // Limits the depth of recursive calls of @tree_list_search_deep
   // Is used to prevent stack overflow.
   // @dir - direction: true - enter recursive call, false - leave call;
   // @ctx - mandatory user dependent context.
   // Returns, if @dir is 'true':
   // - true: recursive call is possible;
   // - false: recursive call is impossible;
   // Returns, if @dir is 'false': does not matter;
   bool scpi_search_recursive_limiter( bool dir, void * ctx );

   // @treelist_recursive_limiter
   // Function-wrapper for Tree-List.
   // Limits the depth of recursive calls of @tree_list_search_deep
   // Is used to prevent stack overflow.
   // @dir - direction: true - enter recursive call, false - leave call;
   // @ctx - mandatory user dependent context.
   // Returns, if @dir is 'true':
   // - true: recursive call is possible;
   // - false: recursive call is impossible;
   // Returns, if @dir is 'false': does not matter;
   static inline bool treelist_recursive_limiter( bool dir, void * ctx )
   {
       return scpi_search_recursive_limiter( dir, ctx );
   }
   #endif
   // ========================================================================================================

   // @sScpiCmdGetNextKey_t
   // Used in @scpi_command_getnext_key
   // Search key context.
   typedef struct
   {
      sStrToken_t found_token;   // current command mnemonic token
      sStrToken_t full_token;    // full command line token
   }
   sScpiCmdGetNextKey_t;
   // ========================================================================================================
   // @sTreeListSearchCtx_t
   // SCPI Command search context
   typedef struct
   {
      #if TREE_LIST_RECURSIVE_LIMIT_ENABLE
      int call_depth; // recursive call depth
      #endif

      sScpiCmdGetNextKey_t cmdKey; // command key iterator context

      const sTreeList_t * parent;  // parent of found SCPI command node
   }
   sTreeListSearchCtx_t;
   // ========================================================================================================
   // @scpi_command_getnext_key
   // Get next command mnemonic token in the chain specified in @ctx
   // @ctx - SCPI command search context;
   // Returns:
   //  NULL - no key found / end of the command line;
   //  NON NULL: string token containing command mnemonic (key)
   const sStrToken_t* scpi_command_getnext_key( sScpiCmdGetNextKey_t * ctx );

   #if 0
   // @scpi_command_getnext_prepare
   // Prepare context for @scpi_command_getnext_key before calling @tree_list_search_deep
   // @ctx - search key context, is used to iterate upon the command mnemonic chain (compound command)
   // @cmd_shead - compound SCPI command mnemonic head
   // @cmd_stail - compound SCPI command mnemonic tail
   void scpi_command_getnext_prepare( sScpiCmdGetNextKey_t * ctx, const char * cmd_shead, const char * cmd_stail );
   #endif

   // @scpi_command_search_prepare
   // Prepare the SCPI Command search context before calling @tree_list_search_deep
   // @ctx - search context, is used in call of @tree_list_search_deep
   // @cmd_shead - compound SCPI command mnemonic head
   // @cmd_stail - compound SCPI command mnemonic tail
   void scpi_command_search_prepare( sTreeListSearchCtx_t * ctx, const char * cmd_shead, const char * cmd_stail );

   // @treelist_getnext_key
   // Function-wrapper for Tree-List.
   // Get next key in the chain for search 
   // @ctx - routine context;
   // Returns:
   //  NULL - no key found / end of the chain;
   //  NON NULL: valid key to continue searching
   static inline const void * treelist_getnext_key( void * _ctx )
   {
       sTreeListSearchCtx_t * ctx = (sTreeListSearchCtx_t*)_ctx;

       return scpi_command_getnext_key( &ctx->cmdKey );
   }

   // @scpi_command_command_found
   // SCPI search command result notifee.
   void scpi_command_command_found( sTreeListSearchCtx_t * ctx, const sTreeList_t * found, const sTreeList_t * parent );

   // @treelist_result_agree
   // Function-wrapper for Tree-List.
   // Tree list result notification/agreeing function.
   // Notifies the SCPI-level about found command node and agrees the first search result.
   static inline bool treelist_result_agree( const sTreeList_t * found, const sTreeList_t * parent, void * _ctx )
   {
       sTreeListSearchCtx_t * ctx = (sTreeListSearchCtx_t*)_ctx;

       scpi_command_command_found( ctx, found, parent );

       return true; // agree result
   }

   // ========================================================================================================
   // @scpi_commands_tlds - functional set for @tree_list_search_deep
   extern const sTreeListSearchDeep_FSet_t scpi_commands_tlds;
   // ========================================================================================================
#endif