/*
 * Copyright (c) 2019 - 2021 Stefan Strobel <stefan.strobel@shimatta.net>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

/**
 * @file    shellmatta_utils.h
 * @brief   util/helper functions of shellmatta
 * @author  Stefan Strobel <stefan.strobel@shimatta.net>
 */

/**
 * @addtogroup shellmatta_utils
 * @{
 */
#ifndef _SHELLMATTA_UTILS_H_
#define _SHELLMATTA_UTILS_H_

#include "shellmatta.h"
#include <stdint.h>

/**
 * @brief       returns the minimum of a and b
 * @param[in]   a   parameter a
 * @param[in]   b   parameter b
 */
#define SHELLMATTA_MIN(a,b) (((a) > (b)) ?  (b) : (a))

/**
 * @brief       returns the maximum of a and b
 * @param[in]   a   parameter a
 * @param[in]   b   parameter b
 */
#define SHELLMATTA_MAX(a,b) (((a) < (b)) ?  (b) : (a))

/**
 * @brief       calls fct with cnt bytes from buffer (to print cnt same bytes)
 * @param[in]   buffer  buffer to send (shall contain the same char)
 * @param[in]   cnt     count of bytes to send
 * @param[in]   fct     write function
 */
#define SHELLMATTA_PRINT_BUFFER(buffer,cnt,fct) \
    while((cnt) > sizeof((buffer)))             \
    {                                           \
        (cnt) -= sizeof((buffer));              \
        (fct)((buffer), sizeof((buffer)));      \
    }                                           \
    if((cnt) != 0u)                             \
    {                                           \
        (fct)((buffer), (cnt));                 \
    }

/** @brief help command which prints all shellmatta commands as table */
extern const shellmatta_cmd_t helpCmd;

/** @brief magic used to check if a shellmatta instance is initiated */
#define SHELLMATTA_MAGIC    0x5101E110u

/** @brief overwritable output buffer size */
#ifndef SHELLMATTA_OUTPUT_BUFFER_SIZE
#define SHELLMATTA_OUTPUT_BUFFER_SIZE   128u
#endif

/** @defgroup Shellmatta Help command overwrites
 *  @{
 *  overwritable help command parameters - the help command is built in and cannot be removed, but you can change
 *  the command, alias and help texts by defining them in your build process  
 *  To change the settings set one of these defines:  
 *  #SHELLMATTA_HELP_COMMAND        to overwrite the help command  
 *  #SHELLMATTA_HELP_ALIAS          to overwrite the help alias  
 *  #SHELLMATTA_HELP_HELP_TEXT      to overwrite the help text  
 *  #SHELLMATTA_HELP_USAGE_TEXT     to overwrite the usage text  
 *  e.g. use _-DSHELLMATTA_HELP_ALIAS=\"?\"_ as compile option to change the alias to ?
 */
#ifndef SHELLMATTA_HELP_COMMAND
#define SHELLMATTA_HELP_COMMAND     (char*)"help"                   /**< help command               */
#endif
#ifndef SHELLMATTA_HELP_ALIAS
#define SHELLMATTA_HELP_ALIAS       (char*)"h"                      /**< help command alias         */
#endif
#ifndef SHELLMATTA_HELP_HELP_TEXT
#define SHELLMATTA_HELP_HELP_TEXT   (char*)"Print this help text"   /**< help command help text     */
#endif
#ifndef SHELLMATTA_HELP_USAGE_TEXT
#define SHELLMATTA_HELP_USAGE_TEXT  (char*)"help"                   /**< help command usage text    */
#endif
/**
 *  @}
 */

void utils_writeEcho(   shellmatta_instance_t   *inst,
                        const char              *data,
                        uint32_t                length);
uint32_t utils_shellItoa(int32_t value, char *buffer, uint32_t base);
void utils_saveCursorPos(shellmatta_instance_t *inst);
void utils_restoreCursorPos(shellmatta_instance_t *inst);
void utils_eraseLine(shellmatta_instance_t *inst);
void utils_rewindCursor(shellmatta_instance_t *inst, uint32_t length);
void utils_forwardCursor(shellmatta_instance_t *inst, uint32_t length);
void utils_insertChars( shellmatta_instance_t   *inst,
                        char                    *data,
                        uint32_t                 length);
void utils_removeChars( shellmatta_instance_t   *inst,
                        uint32_t                 length,
                        bool                     backspace);
void utils_clearInput(shellmatta_instance_t *inst);
void utils_terminateInput(shellmatta_instance_t *inst);

#endif

/** @} */