/* -*- mode: c++; indent-tabs-mode: nil -*- */
/*
    qc_qore.qpp

    Qore Programming Language

    Copyright (C) 2003 - 2023 Qore Technologies, s.r.o.

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.

    Note that the Qore library is released under a choice of three open-source
    licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
    information.
*/

#include <qore/Qore.h>
#include "qore/intern/QC_File.h"

DLLEXPORT extern QoreClass* QC_FILEINPUTSTREAM;
DLLEXPORT extern QoreClass* QC_FILEOUTPUTSTREAM;

#ifdef WORDS_BIGENDIAN
#define Q_MACHINE_MSB 1
#else
#define Q_MACHINE_MSB 0
#endif

#ifdef _Q_WINDOWS
#define Q_IS_WINDOWS 1
#define Q_IS_UNIX    0
#else
#define Q_IS_WINDOWS 0
#define Q_IS_UNIX    1
#endif

/** @defgroup type_code_constants Type Code Constants
    Type code constants as returned by <value>::typeCode()
*/
///@{
//! type code for wildcard types (both with - \c "all" and without - \c "auto" type stripping)
/** @since %Qore 0.9.4
*/
const NT_ALL = NT_ALL;

//! type code for @ref nothing "no value" (@ref nothing)
const NT_NOTHING = NT_NOTHING;

//! type code for @ref integer "integer values"
const NT_INT = NT_INT;

//! type code for @ref float "float values"
const NT_FLOAT = NT_FLOAT;

//! type code for @ref number "number values"
const NT_NUMBER = NT_NUMBER;

//! type code for @ref string "string values"
const NT_STRING = NT_STRING;

//! type code for @ref date "date/time values"
const NT_DATE = NT_DATE;

//! type code for @ref boolean "boolean values"
const NT_BOOLEAN = NT_BOOLEAN;

//! type code for @ref null
const NT_NULL = NT_NULL;

//! type code for @ref binary "binary values"
const NT_BINARY = NT_BINARY;

//! type code for @ref list "list values"
const NT_LIST = NT_LIST;

//! type code for @ref hash "hash values"
const NT_HASH = NT_HASH;

//! type code for @ref object "objects"
const NT_OBJECT = NT_OBJECT;

//! type code for @ref closure "closures"
const NT_CLOSURE = NT_RUNTIME_CLOSURE;

//! type code for @ref call_reference "call references"
const NT_CALLREF = NT_FUNCREF;
///@}

/** @defgroup type_code_map_constants Type Code Map Constants
    Type code map constants to look up type codes (as returned by <value>::typeCode()) from type
    names (as returned by <value>::type()) and vice-versa.
*/
///@{
//! type code map, looks up type names from type code values
const TypeCodeMap = (
    "0": "nothing",
    "1": "integer",
    "2": "float",
    "3": "string",
    "4": "date",
    "5": "bool",
    "6": "NULL",
    "7": "binary",
    "8": "list",
    "9": "hash",
    "10": "object",
    "11": "number",
    "29": "call reference",
    "32": "closure",
);

//! type name map, looks up type codes from type names
const TypeNameMap = (
    "nothing": NT_NOTHING,
    "integer": NT_INT,
    "float": NT_FLOAT,
    "number": NT_NUMBER,
    "string": NT_STRING,
    "date": NT_DATE,
    "bool": NT_BOOLEAN,
    "NULL": NT_NULL,
    "binary": NT_BINARY,
    "list": NT_LIST,
    "hash": NT_HASH,
    "object": NT_OBJECT,
    "call reference": NT_FUNCREF,
    "closure": NT_RUNTIME_CLOSURE,
);
///@}

/** @defgroup boolean_constants Boolean Constants
 */
///@{
//! logical @ref True
const True = bool(true);

//! logical @ref False
const False = bool(false);
///@}

/** @defgroup null_and_nothing_constants NULL and NOTHING Constants
 */
///@{
//! a constant representing the lack of a value
const NOTHING = qore(&Nothing);

//! logical @ref False
const NULL = qore(&Null);
///@}

/** @defgroup exception_type_constants Exception Type Constants
 */
///@{
//! Exception type code system exceptions (thrown in internal %Qore code or in modules)
const ET_System = "System";

//! Exception type for user exceptions (thrown by the @ref throw "throw statement")
const ET_User = "User";
///@}

/** @defgroup call_type_constants Call Type Constants
 */
///@{
//! Call type for user code
const CT_User = CT_USER;

//! Call type for builtin code
const CT_Builtin = CT_BUILTIN;

//! Call type for the start of a new thread by the @ref background "background operator"
const CT_NewThread = CT_NEWTHREAD;

//! Call type for an exception thrown by the @ref rethrow "rethrow statement"
const CT_Rethrow = CT_RETHROW;
///@}

/** @defgroup system_and_build_constants System and Build Constants
 */
///@{
//! The full %Qore version string
const VersionString = qore(new QoreStringNode(qore_version_string));

//! The integer %Qore major version number
const VersionMajor =  qore(qore_version_major);

//! The integer %Qore minor version number
const VersionMinor =  qore(qore_version_minor);

//! The integer %Qore sub version number
const VersionSub =    qore(qore_version_sub);

//! The integer %Qore build number
const Build =         qore(qore_build_number);

//! The string for the platform's CPU architecture
const PlatformCPU =   qore(new QoreStringNode(TARGET_ARCH));

//! A string giving the platform operating-system name
const PlatformOS =    qore(new QoreStringNode(TARGET_OS));

//! The host name of the host used to build the %Qore library
const BuildHost =     qore(new QoreStringNode(qore_build_host));

//! A string giving the C++ compiler used to build %Qore
const Compiler =      qore(new QoreStringNode(qore_cplusplus_compiler));

//! A string giving the C++ compiler flags used to build %Qore
const CFLAGS =        qore(new QoreStringNode(qore_cflags));

//! A string giving the linker flags used to build %Qore
const LDFLAGS =       qore(new QoreStringNode(qore_ldflags));

//! @ref True if the current machine uses <a href="http://en.wikipedia.org/wiki/Most_significant_bit">big-endian or MSB byte order</a> or @ref False if the current machine uses <a href="http://en.wikipedia.org/wiki/Least_significant_bit">little-endian or LSB byte order</a>
const MACHINE_MSB =   bool(Q_MACHINE_MSB);

//! hash of platform information
const Platform = ("OS": qore(new QoreStringNode(TARGET_OS)), "CPU": qore(new QoreStringNode(TARGET_ARCH)), "Unix": bool(Q_IS_UNIX), "Windows": bool(Q_IS_WINDOWS));

//! platform-specific directory separator character string
/** @note \c "/" on Unix-like platforms, \c "\\" on Windows

    @see PathSep
 */
const DirSep = qore(new QoreStringNode(QORE_DIR_SEP_STR));

//! platform-specific path separator character string
/** @note \c ":" on Unix-like platforms, \c ";" on Windows

    @see DirSep

    @since %Qore 0.8.13
 */
const PathSep = qore(new QoreStringNode(QORE_PATH_SEP_STR));
///@}

/** @defgroup event_source_constants Event Source Constants
 */
///@{
//! @ref Socket "Socket class" source code
const SOURCE_SOCKET = QORE_SOURCE_SOCKET;

//! @ref HTTPClient "HTTPClient class" source code
const SOURCE_HTTPCLIENT = QORE_SOURCE_HTTPCLIENT;

//! @ref FtpClient "FtpClient class" source code
const SOURCE_FTPCLIENT = QORE_SOURCE_FTPCLIENT;

//! @ref File "File class" source code
const SOURCE_FILE = QORE_SOURCE_FILE;
///@}

/** @defgroup event_map_constants Event Map Constants
 */
///@{
//! Maps from @ref event_source_constants (the keys) to descriptive strings (the values)
const EVENT_SOURCE_MAP = (
    "1": "SOCKET",
    "2": "HTTPCLIENT",
    "3": "FTPCLIENT",
    "4": "FILE",
);

//! Maps from @ref event_constants (the keys) to descriptive strings (the values)
const EVENT_MAP = (
    "1": "PACKET_READ",
    "2": "PACKET_SENT",
    "3": "HTTP_CONTENT_LENGTH",
    "4": "HTTP_CHUNKED_START",
    "5": "HTTP_CHUNKED_END",
    "6": "HTTP_REDIRECT",
    "7": "CHANNEL_CLOSED",
    "8": "DELETED",
    "9": "FTP_SEND_MESSAGE",
    "10": "FTP_MESSAGE_RECEIVED",
    "11": "HOSTNAME_LOOKUP",
    "12": "HOSTNAME_RESOLVED",
    "13": "HTTP_SEND_MESSAGE",
    "14": "HTTP_MESSAGE_RECEIVED",
    "15": "HTTP_FOOTERS_RECEIVED",
    "16": "HTTP_CHUNKED_DATA_RECEIVED",
    "17": "HTTP_CHUNK_SIZE",
    "18": "CONNECTING",
    "19": "CONNECTED",
    "20": "START_SSL",
    "21": "SSL_ESTABLISHED",
    "22": "OPEN_FILE",
    "23": "FILE_OPENED",
    "24": "DATA_READ",
    "25": "DATA_WRITTEN",
    "26": "HTTP_CHUNKED_DATA_READ",
    "27": "HTTP_CHUNKED_DATA_SENT",
    "28": "HTTP_FOOTERS_SENT",
    "29": "SOCKET_DATA_READ",
    "30": "SOCKET_DATA_SENT",
    "31": "HTTP_HEADERS_READ",
);
///@}

/** @defgroup event_constants Event Constants
 */
///@{
//! Raised when a network packet is received
const EVENT_PACKET_READ = QORE_EVENT_PACKET_READ;

//! Raised when a network packet is sent
const EVENT_PACKET_SENT = QORE_EVENT_PACKET_SENT;

//! Raised when the HTTP \c "Content-Length" header is received
const EVENT_HTTP_CONTENT_LENGTH = QORE_EVENT_HTTP_CONTENT_LENGTH;

//! Raised when HTTP chunked data is about to be received
const EVENT_HTTP_CHUNKED_START = QORE_EVENT_HTTP_CHUNKED_START;

//! Raised when all HTTP chunked data has been received
const EVENT_HTTP_CHUNKED_END = QORE_EVENT_HTTP_CHUNKED_END;

//! Raised when an HTTP redirect message is received
const EVENT_HTTP_REDIRECT = QORE_EVENT_HTTP_REDIRECT;

//! Raised when a socket or file is closed
const EVENT_CHANNEL_CLOSED = QORE_EVENT_CHANNEL_CLOSED;

//! Raised when the object being monitored is deleted
const EVENT_DELETED = QORE_EVENT_DELETED;

//! Raised immediately before an FTP control message is sent
const EVENT_FTP_SEND_MESSAGE = QORE_EVENT_FTP_SEND_MESSAGE;

//! Raised when an FTP reply is received on the control channel
const EVENT_FTP_MESSAGE_RECEIVED = QORE_EVENT_FTP_MESSAGE_RECEIVED;

//! Raised when a hostname lookup is started
const EVENT_HOSTNAME_LOOKUP = QORE_EVENT_HOSTNAME_LOOKUP;

//! Raised when a hostname lookup is resolved
const EVENT_HOSTNAME_RESOLVED = QORE_EVENT_HOSTNAME_RESOLVED;

//! Raised when an HTTP message is sent
const EVENT_HTTP_SEND_MESSAGE = QORE_EVENT_HTTP_SEND_MESSAGE;

//! Raised when an HTTP message is received
const EVENT_HTTP_MESSAGE_RECEIVED = QORE_EVENT_HTTP_MESSAGE_RECEIVED;

//! Raised when HTTP footers are received
const EVENT_HTTP_FOOTERS_RECEIVED = QORE_EVENT_HTTP_FOOTERS_RECEIVED;

//! Raised when a block of HTTP chunked data is received
const EVENT_HTTP_CHUNKED_DATA_RECEIVED = QORE_EVENT_HTTP_CHUNKED_DATA_RECEIVED;

//! Raised when the next chunk size for HTTP chunked data is known
const EVENT_HTTP_CHUNK_SIZE = QORE_EVENT_HTTP_CHUNK_SIZE;

//! Raised right before a socket connection attempt is made
const EVENT_CONNECTING = QORE_EVENT_CONNECTING;

//! Raised when the socket connection has been established
const EVENT_CONNECTED = QORE_EVENT_CONNECTED;

//! Raised when socket SSL negotiation starts
const EVENT_START_SSL = QORE_EVENT_START_SSL;

//! Raised when SSL communication has been negotiated and established
const EVENT_SSL_ESTABLISHED = QORE_EVENT_SSL_ESTABLISHED;

//! Raised right before a file is opened
const EVENT_OPEN_FILE = QORE_EVENT_OPEN_FILE;

//! Raised when a file has been successfully opened
const EVENT_FILE_OPENED = QORE_EVENT_FILE_OPENED;

//! Raised when data has been read from a file
const EVENT_DATA_READ = QORE_EVENT_DATA_READ;

//! Raised when data has been written to a file
const EVENT_DATA_WRITTEN = QORE_EVENT_DATA_WRITTEN;

//! Raised when data is read if the event data flag is set
/** @since %Qore 0.9.4
*/
const EVENT_HTTP_CHUNKED_DATA_READ = QORE_EVENT_HTTP_CHUNKED_DATA_READ;

//! Raised when data is sent if the event data flag is set
/** @since %Qore 0.9.4
*/
const EVENT_HTTP_CHUNKED_DATA_SENT = QORE_EVENT_HTTP_CHUNKED_DATA_SENT;

//! Raised when HTTP footers are sent while receiving chunked data if the event data flag is set
/** @since %Qore 0.9.4
*/
const EVENT_HTTP_CHUNKED_FOOTERS_SENT = QORE_EVENT_HTTP_FOOTERS_SENT;

//! Raised when data is read on the socket if the event data flag is set
/** @since %Qore 0.9.4
*/
const EVENT_SOCKET_DATA_READ = QORE_EVENT_SOCKET_DATA_READ;

//! Raised when data is sent on the socket if the event data flag is set
/** @since %Qore 0.9.4
*/
const EVENT_SOCKET_DATA_SENT = QORE_EVENT_SOCKET_DATA_SENT;

//! Raised when HTTP headers are received
/** @since %Qore 0.9.4
*/
const EVENT_HTTP_HEADERS_READ = QORE_EVENT_HTTP_HEADERS_READ;
///@}

/** @defgroup io_constants I/O Constants
    These constants are all instantiations of the @ref File "File class"

    None of these constants are available if the parse option @ref PO_NO_TERMINAL_IO is set
 */
///@{
//! system constant for stdin (file descriptor 0)
const stdin = qore(QC_FILE->execSystemConstructor(0));

//! system constant for stdout (file descriptor 1)
const stdout = qore(QC_FILE->execSystemConstructor(1));

//! system constant for stderr (file descriptor 2)
const stderr = qore(QC_FILE->execSystemConstructor(2));

//! system constant for stdin InputStream (file descriptor 0)
const stdin_stream = qore(QC_FILEINPUTSTREAM->execSystemConstructor(0));

//! system constant for stdout OutputStream (file descriptor 1)
const stdout_stream = qore(QC_FILEOUTPUTSTREAM->execSystemConstructor(1));

//! system constant for stderr OutputStream (file descriptor 2)
const stderr_stream = qore(QC_FILEOUTPUTSTREAM->execSystemConstructor(2));
///@}
