/* Copyright (C) 2019-2020  Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#ifndef _LIBIGLOO__ERROR_H_
#define _LIBIGLOO__ERROR_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <igloo/config.h>
#include <igloo/types.h>

typedef uint32_t igloo_error_flag_t;

typedef enum {
    /* POSIX errno (<errno.h>, E*) */
    igloo_ERROR_DOMAIN_ERRNO,
    /* RoarAudio error codes (https://specifications.loewenfelsen.net/v0/ra-errors) */
    igloo_ERROR_DOMAIN_RA_ERROR
} igloo_error_domain_t;

typedef struct {
    /* Control structure */
    igloo_control_t control;
    /* error code */
    const igloo_error_t error;
    /* flags */
    igloo_error_flag_t flags;
    /* UUID for this error */
    const char *uuid;
    /* akindof as per report XML or NULL */
    const char *akindof;
    /* name of the error */
    const char *name;
    /* error message for the error */
    const char *message;
    /* description of the error code */
    const char *description;
} igloo_error_desc_t;

/*
 * IMPORTANT:   The following list is not to be understood as a complete list.
 *              libigloo can at any time return error codes not defined here.
 * NOTE:        The following lines must keep their exact formating as it is used for code generation!
 *              Values in the range of [-1:65535] are reserved for RoarAudio error codes.
 *              See: https://specifications.loewenfelsen.net/v0/ra-errors
 *              The value -2 is reserved for testing and no error must be assigned to it.
 *              libigloo specific errors MUST be added with a value < -2.
 */
#define igloo_ERRORTESTVECTOR_NX    ((igloo_error_t) -2) /* /!\ Special value for testing. No error must be defined for this /!\ */
#define igloo_ERROR_GENERIC         ((igloo_error_t) -1) /* Generic error: A generic error occurred. */
#define igloo_ERROR_NONE            ((igloo_error_t)  0) /* No error: The operation succeeded. */
#define igloo_ERROR_PERM            ((igloo_error_t)  1) /* Operation not permitted */
#define igloo_ERROR_NOENT           ((igloo_error_t)  2) /* No such file, directory, or object */
#define igloo_ERROR_BUSY            ((igloo_error_t)  4) /* Device or resource busy */
#define igloo_ERROR_CONNREFUSED     ((igloo_error_t)  5) /* Connection refused */
#define igloo_ERROR_NOSYS           ((igloo_error_t)  6) /* Function not implemented */
#define igloo_ERROR_RANGE           ((igloo_error_t) 10) /* Result out of range */
#define igloo_ERROR_NOMEM           ((igloo_error_t) 12) /* Not enough space */
#define igloo_ERROR_INVAL           ((igloo_error_t) 13) /* Invalid argument */
#define igloo_ERROR_BADRQC          ((igloo_error_t) 15) /* Invalid request code */
#define igloo_ERROR_DOM             ((igloo_error_t) 16) /* Mathematics argument out of domain of function */
#define igloo_ERROR_FAULT           ((igloo_error_t) 18) /* Invalid address */
#define igloo_ERROR_IO              ((igloo_error_t) 19) /* I/O-Error */
#define igloo_ERROR_LOOP            ((igloo_error_t) 22) /* Too many recursions */
#define igloo_ERROR_TYPEMM          ((igloo_error_t) 39) /* Type mismatch: Object of different type required */
#define igloo_ERROR_NOTCONN         ((igloo_error_t) 41) /* Socket or object not connected */
#define igloo_ERROR_TIMEDOUT        ((igloo_error_t) 46) /* Connection timed out */
#define igloo_ERROR_AGAIN           ((igloo_error_t) 47) /* Resource temporarily unavailable */
#define igloo_ERROR_LINKDOWN        ((igloo_error_t) 49) /* Physical or logical link down */
#define igloo_ERROR_ILLSEQ          ((igloo_error_t) 56) /* Illegal byte sequence */
#define igloo_ERROR_ADDRINUSE       ((igloo_error_t) 57) /* Address in use */
#define igloo_ERROR_NSVERSION       ((igloo_error_t) 60) /* Not supported version */
#define igloo_ERROR_INPROGRESS      ((igloo_error_t) 73) /* Operation in progress */
#define igloo_ERROR_NETUNREACH      ((igloo_error_t) 75) /* Network unreachable */
#define igloo_ERROR_ISCONN          ((igloo_error_t) 80) /* Socket/Object is connected */
#define igloo_ERROR_CONNRST         ((igloo_error_t) 82) /* Connection reset */
#define igloo_ERROR_DESTADDRREQ     ((igloo_error_t) 87) /* Destination address required */
#define igloo_ERROR_AFNOTSUP        ((igloo_error_t) 88) /* Address family not supported */
#define igloo_ERROR_SWITCHPROTO     ((igloo_error_t) 99) /* Switch protocol */
#define igloo_ERROR_GONE            ((igloo_error_t)104) /* Resource gone */
#define igloo_ERROR_BADSTATE        ((igloo_error_t)109) /* Object is in bad/wrong state */

const igloo_error_desc_t *      igloo_error_get_description(igloo_error_t error) igloo_ATTR_F_WARN_UNUSED_RESULT igloo_ATTR_F_PURE;
const igloo_error_desc_t *      igloo_error_getbyname(const char *name) igloo_ATTR_F_WARN_UNUSED_RESULT igloo_ATTR_F_PURE;

/* Convert an error from another error domain.
 *
 * This converts an error from another error domain and returns it as igloo_error_t.
 *
 * Parameters:
 *  domain
 *      The domain to convert from.
 *  value
 *      The error value to convert.
 *  error
 *      Set to the error of this function. Can be NULL.
 * Returns:
 *  The converted error. Will return igloo_ERROR_GENERIC if this function fails.
 */
igloo_error_t                   igloo_error_by_domain(igloo_error_domain_t domain, intmax_t value, igloo_error_t *error) igloo_ATTR_F_WARN_UNUSED_RESULT igloo_ATTR_F_PURE;

/* Gets and converts the current error from the system.
 *
 * Parameters:
 *  error
 *      Set to the error of this function. Can be NULL.
 * Returns:
 *  The converted error. Will return igloo_ERROR_GENERIC if this function fails.
 */
igloo_error_t                   igloo_error_from_system(igloo_error_t *error) igloo_ATTR_F_WARN_UNUSED_RESULT;

/* Clears the system's current error.
 *
 * Returns:
 *  igloo_ERROR_NONE, or any error if the current system error can not be cleared.
 */
igloo_error_t                   igloo_error_clear_system(void);

#ifdef __cplusplus
}
#endif

#endif /* ! _LIBIGLOO__ERROR_H_ */
