/*
 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
 *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
 *
 * This file is part of lsp-common-lib
 * Created on: 25 марта 2016 г.
 *
 * lsp-common-lib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * lsp-common-lib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with lsp-common-lib. If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef LSP_PLUG_IN_COMMON_STATUS_H_
#define LSP_PLUG_IN_COMMON_STATUS_H_

#include <lsp-plug.in/common/version.h>
#include <lsp-plug.in/common/types.h>

#define LSP_STATUS_ASSERT(x, ...)       do { status_t __res__ = (x); if (__res__ != STATUS_OK) { __VA_ARGS__; return __res__; } } while(false)
#define LSP_VSTATUS_ASSERT(x, ...)      do { status_t __res__ = (x); if (__res__ != STATUS_OK) { __VA_ARGS__; return; } } while(false)
#define LSP_BOOL_ASSERT(x, res, ...)    do { if (!(x)) { __VA_ARGS__; return res; } } while(false)

namespace lsp
{
    /**
     * Status type
     */
    typedef int         status_t;

    /**
     * Definition of different status codes used in LSP project
     */
    enum status_codes
    {
        STATUS_OK,                      //!< STATUS_OK successful status
        STATUS_UNSPECIFIED,             //!< STATUS_UNSPECIFIED
        STATUS_LOADING,                 //!< STATUS_LOADING
        STATUS_IN_PROCESS,              //!< STATUS_IN_PROCESS
        STATUS_UNKNOWN_ERR,             //!< STATUS_UNKNOWN_ERR
        STATUS_NO_MEM,                  //!< STATUS_NO_MEM
        STATUS_NOT_FOUND,               //!< STATUS_NOT_FOUND
        STATUS_BAD_FORMAT,              //!< STATUS_BAD_FORMAT
        STATUS_UNSUPPORTED_FORMAT,      //!< STATUS_UNSUPPORTED_FORMAT
        STATUS_CORRUPTED_FILE,          //!< STATUS_CORRUPTED_FILE
        STATUS_NO_DATA,                 //!< STATUS_NO_DATA
        STATUS_INVALID_UID,             //!< STATUS_INVALID_UID
        STATUS_DISCONNECTED,            //!< STATUS_DISCONNECTED
        STATUS_BAD_ARGUMENTS,           //!< STATUS_BAD_ARGUMENTS
        STATUS_NOT_BOUND,               //!< STATUS_NOT_BOUND
        STATUS_BAD_STATE,               //!< STATUS_BAD_STATE
        STATUS_NOT_IMPLEMENTED,         //!< STATUS_NOT_IMPLEMENTED
        STATUS_ALREADY_EXISTS,          //!< STATUS_ALREADY_EXISTS
        STATUS_OVERFLOW,                //!< STATUS_OVERFLOW
        STATUS_BAD_HIERARCHY,           //!< STATUS_BAD_HIERARCHY
        STATUS_DUPLICATED,              //!< STATUS_DUPLICATED
        STATUS_TOO_BIG,                 //!< STATUS_TOO_BIG
        STATUS_PERMISSION_DENIED,       //!< STATUS_PERMISSION_DENIED
        STATUS_IO_ERROR  ,              //!< STATUS_IO_ERROR
        STATUS_NO_FILE,                 //!< STATUS_NO_FILE
        STATUS_EOF,                     //!< STATUS_EOF
        STATUS_CLOSED,                  //!< STATUS_CLOSED
        STATUS_NOT_SUPPORTED,           //!< STATUS_NOT_SUPPORTED
        STATUS_INVALID_VALUE,           //!< STATUS_INVALID_VALUE
        STATUS_BAD_LOCALE,              //!< STATUS_BAD_LOCALE
        STATUS_NO_DEVICE,               //!< STATUS_NO_DEVICE
        STATUS_UNSUPPORTED_DEVICE,      //!< STATUS_UNSUPPORTED_DEVICE
        STATUS_OPENED,                  //!< STATUS_OPENED
        STATUS_BAD_TYPE,                //!< STATUS_BAD_TYPE
        STATUS_CORRUPTED,               //!< STATUS_CORRUPTED
        STATUS_INSUFFICIENT,            //!< STATUS_INSUFFICIENT
        STATUS_KILLED,                  //!< STATUS_KILLED
        STATUS_TIMED_OUT,               //!< STATUS_TIMED_OUT
        STATUS_FAILED,                  //!< STATUS_FAILED
        STATUS_SKIP,                    //!< STATUS_SKIP
        STATUS_CANCELLED,               //!< STATUS_CANCELLED
        STATUS_NOT_EMPTY,               //!< STATUS_NOT_EMPTY
        STATUS_IS_DIRECTORY,            //!< STATUS_IS_DIRECTORY
        STATUS_NOT_DIRECTORY,           //!< STATUS_NOT_DIRECTORY
        STATUS_REMOVED,                 //!< STATUS_REMOVED
        STATUS_BREAK_POINT,             //!< STATUS_BREAK_POINT  This is special status for step-by-step tracing algorithms
        STATUS_READONLY,                //!< STATUS_READONLY
        STATUS_NULL,                    //!< STATUS_NULL
        STATUS_LOCKED,                  //!< STATUS_LOCKED
        STATUS_REJECTED  ,              //!< STATUS_REJECTED
        STATUS_ALREADY_BOUND,           //!< STATUS_ALREADY_BOUND
        STATUS_NO_CAPTURES,             //!< STATUS_NO_CAPTURES
        STATUS_NO_SOURCES,              //!< STATUS_NO_SOURCES
        STATUS_BAD_PATH,                //!< STATUS_BAD_PATH
        STATUS_PROTOCOL_ERROR,          //!< STATUS_PROTOCOL_ERROR
        STATUS_BAD_TOKEN,               //!< STATUS_BAD_TOKEN
        STATUS_NO_GRAB,                 //!< STATUS_NO_GRAB
        STATUS_UNDERFLOW,               //!< STATUS_UNDERFLOW
        STATUS_INCOMPATIBLE,            //!< STATUS_INCOMPATIBLE The module/function is not compatible
        STATUS_NOT_MAPPED,              //!< STATUS_NOT_MAPPED the resource is not mapped
        STATUS_RETRY,                   //!< STATUS_RETRY need to retry the call
        STATUS_INTERRUPTED,             //!< STATUS_INTERRUPTED the call has been interrupted
        STATUS_NOT_FILE,                //!< STATUS_NOT_FILE not a regular file
        STATUS_BAD_SYMLINK,             //!< STATUS_BAD_SYMMLINK bad symbolic link

        STATUS_TOTAL,
        STATUS_MAX = STATUS_TOTAL - 1,
        STATUS_SUCCESS = STATUS_OK      //!< STATUS_SUCCESS an alias to STATUS_OK
    };

    /**
     * Get string definition of the corresponding status
     * @param code status code
     * @return pointer to status string or NULL if the value is invalid
     */
    LSP_COMMON_LIB_PUBLIC
    const char *get_status(status_t code);

    /**
     * Get localized key of the corresponding status which may be used
     * while performing localized dictionary lookup
     * @param code status code
     * @return pointer to localization key string or NULL if the value is invalid
     */
    LSP_COMMON_LIB_PUBLIC
    const char *get_status_lc_key(status_t code);

    /**
     * Check that status code is successful
     * @param code status code
     * @return true if status code is successful
     */
    LSP_COMMON_LIB_PUBLIC
    bool        status_is_success(status_t code);

    /**
     * Check that status code is preliminary
     * @param code status code
     * @return true if status code is preliminary
     */
    LSP_COMMON_LIB_PUBLIC
    bool        status_is_preliminary(status_t code);

    /**
     * Check that status code is failure
     * @param code status code
     * @return true if status code is failure
     */
    LSP_COMMON_LIB_PUBLIC
    bool        status_is_error(status_t code);

    /**
     * Update status if it is success with new status
     * @param status the current status
     * @param new_status the new status
     * @return new status if current status is STATUS_OK, otherwise status
     */
    LSP_COMMON_LIB_PUBLIC
    status_t    update_status(status_t status, status_t new_status);
}

#endif /* CORE_STATUS_H_ */
