#ifndef QDB_API_ERROR_H
#define QDB_API_ERROR_H

//! \file error.h
//! \defgroup error Error codes and error handling

/*
 *
 * Official quasardb C API 2.0.02.0.1
 * c64b446 2017-10-09 20:00:48 +0000
 *
 * Copyright (c) 2009-2017, quasardb SAS
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of quasardb nor the names of its contributors may
 *      be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY QUASARDB AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "_attr.h"

#ifdef __cplusplus
extern "C" {
#endif

//  Error code are 32 bit integers computed as follow
//
//  High order to low order
//
//  4-bit - origin
//
//      1111 - Remote system
//      1110 - Local system
//      1101 - Connection
//      1100 - Input
//      1011 - Entry
//
//  4-bit - severity
//
//      0011 - Unrecoverable
//      0010 - Error
//      0001 - Warning - Nothing bad but you might not have the result you want
//      0000 - Info
//
//  8-bit - Reserved
//  16-bit - Code - The actual error code
//
// You are highly ENCOURAGED to use macros to check for errors as in the future
// error handling may change.

//! \defgroup error

// clang-format off

//! \ingroup error
//! \brief The error origin.
typedef enum qdb_err_origin
{
    qdb_e_origin_system_remote      = (int) 0xf0000000,
    qdb_e_origin_system_local       = (int) 0xe0000000,
    qdb_e_origin_connection         = (int) 0xd0000000,
    qdb_e_origin_input              = (int) 0xc0000000,
    qdb_e_origin_operation          = (int) 0xb0000000,
    qdb_e_origin_protocol           = (int) 0xa0000000
} qdb_error_origin_t;

//! \ingroup error
//! \def QDB_ERROR_ORIGIN
//! \brief Extracts the origin out of a ::qdb_error_t
#define QDB_ERROR_ORIGIN(x)         ((int)((x) & 0xf0000000))

//! \ingroup error
//! \brief An error severity level.
typedef enum qdb_err_severity
{
    qdb_e_severity_unrecoverable    = 0x03000000,
    qdb_e_severity_error            = 0x02000000,
    qdb_e_severity_warning          = 0x01000000,
    qdb_e_severity_info             = 0x00000000
} qdb_error_severity_t;

//! \ingroup error
//! \def QDB_ERROR_SEVERITY
//! \brief Extracts the severity out of a ::qdb_error_t
#define QDB_ERROR_SEVERITY(x)       ((x) & 0x0f000000)

//! \ingroup error
//! \def QDB_SUCCESS
//! \brief True if and only if the ::qdb_error_t indicates a success
#define QDB_SUCCESS(x)              (!(x) || (QDB_ERROR_SEVERITY(x) == qdb_e_severity_info))

//! \ingroup error
//! \def QDB_FAILURE
//! \brief True if and only if the ::qdb_error_t indicates a failure
#define QDB_FAILURE(x)              (!QDB_SUCCESS(x))

//! \ingroup error
//! \brief An error code indicating success or failure.
typedef enum qdb_err
{
    qdb_e_ok = 0,

    // ------------------------------------------------------------------------------------------------------
    //  error name                      = origin                     | severity                     | code
    // ------------------------------------------------------------------------------------------------------
    qdb_e_uninitialized                 = qdb_e_origin_input         | qdb_e_severity_unrecoverable | 0xFFFF,
    qdb_e_alias_not_found               = qdb_e_origin_operation     | qdb_e_severity_warning       | 0x0008,
    qdb_e_alias_already_exists          = qdb_e_origin_operation     | qdb_e_severity_warning       | 0x0009,
    qdb_e_out_of_bounds                 = qdb_e_origin_input         | qdb_e_severity_warning       | 0x0019,
    qdb_e_skipped                       = qdb_e_origin_operation     | qdb_e_severity_warning       | 0x0021,
    qdb_e_incompatible_type             = qdb_e_origin_operation     | qdb_e_severity_warning       | 0x0022,
    qdb_e_container_empty               = qdb_e_origin_operation     | qdb_e_severity_warning       | 0x0023,
    qdb_e_container_full                = qdb_e_origin_operation     | qdb_e_severity_warning       | 0x0024,
    qdb_e_element_not_found             = qdb_e_origin_operation     | qdb_e_severity_info          | 0x0025,
    qdb_e_element_already_exists        = qdb_e_origin_operation     | qdb_e_severity_info          | 0x0026,
    qdb_e_overflow                      = qdb_e_origin_operation     | qdb_e_severity_warning       | 0x0027,
    qdb_e_underflow                     = qdb_e_origin_operation     | qdb_e_severity_warning       | 0x0028,
    qdb_e_tag_already_set               = qdb_e_origin_operation     | qdb_e_severity_info          | 0x0029,
    qdb_e_tag_not_set                   = qdb_e_origin_operation     | qdb_e_severity_info          | 0x002a,
    qdb_e_timeout                       = qdb_e_origin_connection    | qdb_e_severity_error         | 0x000a,
    qdb_e_connection_refused            = qdb_e_origin_connection    | qdb_e_severity_unrecoverable | 0x000e,
    qdb_e_connection_reset              = qdb_e_origin_connection    | qdb_e_severity_error         | 0x000f,
    qdb_e_unstable_cluster              = qdb_e_origin_connection    | qdb_e_severity_error         | 0x0012,
    qdb_e_try_again                     = qdb_e_origin_connection    | qdb_e_severity_error         | 0x0017,
    qdb_e_conflict                      = qdb_e_origin_operation     | qdb_e_severity_error         | 0x001a,
    qdb_e_not_connected                 = qdb_e_origin_connection    | qdb_e_severity_error         | 0x001b,
    qdb_e_resource_locked               = qdb_e_origin_operation     | qdb_e_severity_error         | 0x002d,
    // check errno or GetLastError() for actual error
    qdb_e_system_remote                 = qdb_e_origin_system_remote | qdb_e_severity_unrecoverable | 0x0001,
    qdb_e_system_local                  = qdb_e_origin_system_local  | qdb_e_severity_unrecoverable | 0x0001,

    qdb_e_internal_remote               = qdb_e_origin_system_remote | qdb_e_severity_unrecoverable | 0x0002,
    qdb_e_internal_local                = qdb_e_origin_system_local  | qdb_e_severity_unrecoverable | 0x0002,
    qdb_e_no_memory_remote              = qdb_e_origin_system_remote | qdb_e_severity_unrecoverable | 0x0003,
    qdb_e_no_memory_local               = qdb_e_origin_system_local  | qdb_e_severity_unrecoverable | 0x0003,
    qdb_e_invalid_protocol              = qdb_e_origin_protocol      | qdb_e_severity_unrecoverable | 0x0004,
    qdb_e_host_not_found                = qdb_e_origin_connection    | qdb_e_severity_error         | 0x0005,
    qdb_e_buffer_too_small              = qdb_e_origin_input         | qdb_e_severity_warning       | 0x000b,
    qdb_e_not_implemented               = qdb_e_origin_system_remote | qdb_e_severity_unrecoverable | 0x0011,
    qdb_e_invalid_version               = qdb_e_origin_protocol      | qdb_e_severity_unrecoverable | 0x0016,
    qdb_e_invalid_argument              = qdb_e_origin_input         | qdb_e_severity_error         | 0x0018,
    qdb_e_invalid_handle                = qdb_e_origin_input         | qdb_e_severity_error         | 0x001c,
    qdb_e_reserved_alias                = qdb_e_origin_input         | qdb_e_severity_error         | 0x001d,
    qdb_e_unmatched_content             = qdb_e_origin_operation     | qdb_e_severity_info          | 0x001e,
    qdb_e_invalid_iterator              = qdb_e_origin_input         | qdb_e_severity_error         | 0x001f,
    qdb_e_entry_too_large               = qdb_e_origin_input         | qdb_e_severity_error         | 0x002b,
    qdb_e_transaction_partial_failure   = qdb_e_origin_operation     | qdb_e_severity_error         | 0x002c,
    qdb_e_operation_disabled            = qdb_e_origin_operation     | qdb_e_severity_error         | 0x002e,
    qdb_e_operation_not_permitted       = qdb_e_origin_operation     | qdb_e_severity_error         | 0x002f,
    qdb_e_iterator_end                  = qdb_e_origin_operation     | qdb_e_severity_info          | 0x0030,
    qdb_e_invalid_reply                 = qdb_e_origin_protocol      | qdb_e_severity_unrecoverable | 0x0031,
    qdb_e_ok_created                    = qdb_e_origin_operation     | qdb_e_severity_info          | 0x0032,
    qdb_e_no_space_left                 = qdb_e_origin_system_remote | qdb_e_severity_unrecoverable | 0x0033,
    qdb_e_quota_exceeded                = qdb_e_origin_system_remote | qdb_e_severity_error         | 0x0034,
    qdb_e_alias_too_long                = qdb_e_origin_input         | qdb_e_severity_error         | 0x0035,
    qdb_e_clock_skew                    = qdb_e_origin_system_remote | qdb_e_severity_error         | 0x0036,
    qdb_e_access_denied                 = qdb_e_origin_operation     | qdb_e_severity_error         | 0x0037,
    qdb_e_login_failed                  = qdb_e_origin_system_remote | qdb_e_severity_error         | 0x0038
} qdb_error_t;

// clang-format on

//! \ingroup error
//! \brief An alias for ::qdb_error_t
typedef qdb_error_t qdb_status_t;

//! \ingroup client
//! \brief Translates an error code into an English error message
//! \param error The ::qdb_error_t code outputted by another function
//!
//! \return A static, null-terminated string describing the error.
//! The buffer is API managed and should not be freed or written to by the
//! caller.
QDB_API_LINKAGE const char * qdb_error(qdb_error_t error);

#ifdef __cplusplus
} // extern "C"
#endif

#endif // QDB_API_ERROR_H
