/////////////////////////////////////////////////////////////////////
//                                                                 //
// file: Modules_CCA.h
//                                                                 //
/////////////////////////////////////////////////////////////////////
//                                                                 //
// Copyright (c) 2024 Acroname Inc. - All Rights Reserved          //
//                                                                 //
// This file is part of the BrainStem release. See the license.txt //
// file included with this package or go to                        //
// https://acroname.com/software/brainstem-development-kit         //
// for full license details.                                       //
/////////////////////////////////////////////////////////////////////
#ifndef __Modules_CCA_H__
#define __Modules_CCA_H__

#include "CCA_Core.h"
#include "Link_CCA.h" //For linkSpec_CCA

#ifdef CCA_PACK
    #pragma pack(push, CCA_PACK)
#endif
    struct aEtherConfig_CCA {
        bool enabled; /**< True: Client-Server module is used; False: Direct module control is used.*/
        bool fallback; /**< True: If connections fails it will automatically search for network connections; */
        bool localOnly; /**< True: Restricts access to localhost; False: Expose device to external network */
        unsigned short assignedPort; /**< Server assigned port after successful connection*/
        unsigned int networkInterface; /**< Network interface to use for connections.*/
    };
#ifdef CCA_PACK
    #pragma pack(pop)
#endif

/// \defgroup ModuleEntity Module Entity
/// The Module Entity provides a generic interface to a BrainStem hardware module.
/// The Module Class is the parent class for all BrainStem modules. Each module
/// inherits from Module and implements its hardware specific features.

#ifdef __cplusplus
extern "C" {
#endif

    /// Creates a brainstem object that the library will manage internally and creates a
    /// unique identifier that will be used for other function calls in this library.
    /// \param id Unique identifier for the internally created stem.
    /// \param result object, containing NO_ERROR or a non zero Error code.
    aLIBEXPORT void __stdcall module_createStem(unsigned int* id, struct Result* result, unsigned char moduleAddress, bool autoNetworking, unsigned char model);

    /// Disconnects from device defined by the ID and will destroy any internal memory associated with the Device.
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    aLIBEXPORT void __stdcall module_disconnectAndDestroyStem(unsigned int* id, struct Result* result);

    /// Finds and connects to the first device found on the given transport.  If a serial number was provided 
    /// when module_createStem was called then it will only connect to that specific id.
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    /// \param transport Defines what connection method should be searched for BrainStem devices. 
    /// (i.e. USB, TCPIP, etc.)
    aLIBEXPORT void __stdcall module_discoverAndConnect(
        unsigned int* id, 
        struct Result* result, 
        int transport,
        unsigned int serialNumber);

    /// Connect to a link with a fully defined specifier.
    /// \param spec - Connect to module with specifier.
    /// \details ::aErrInitialization - If there is currently no link object.
    /// \details ::aErrBusy - If the link is currently connected.
    /// \details ::aErrParam - if the specifier is incorrect.
    /// \details ::aErrNotFound - if the module cannot be found.
    /// \details ::aErrNone If the connect was successful.
    aLIBEXPORT void __stdcall module_connectFromSpec(
        unsigned int* id,
        struct Result* result,
        struct linkSpec_CCA* spec);

    /// Discovers all of the BrainStem devices on a given transport. The return list is filled
    /// with device specifiers which contains information about the device.
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    /// \param stemList List of device specifiers for each of the discovered devices
    /// \param listLength Indicates how long the list is.
    /// \param transport Defines what connection method should be searched for BrainStem devices.
    ///        (i.e. USB, TCPIP, etc.)
    aLIBEXPORT void __stdcall module_sDiscover(
        unsigned int* id, 
        struct Result* result, 
        struct linkSpec_CCA* stemList, 
        int listLength,
        int transport);

    /// Finds the first module found on the given transport.
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    /// \param spec Pointer to the linkSpec for the requested module if found.
    /// \param transport The transport type on which search for devices. Valid #linkType "linktypes" are accepted
    /// \param networkInterface Defines the network interface to use when multiple are present.
    ///        A value of 0 or LOCALHOST_IP_ADDRESS will result in local searches only.
    ///        Values other than this will have firewall implications.
    aLIBEXPORT void __stdcall module_findFirstModule(
        unsigned int* id,
        struct Result* result,
        struct linkSpec_CCA* spec,
        unsigned int networkInterface,
        int transport);

    /// Finds the module with the given serial number on the given transport type.
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    /// \param spec Pointer to the linkSpec for the requested module if found.
    /// \param serialNumber The serial number of the Module to find.
    /// \param transport The transport type on which search for devices. Valid #linkType "linktypes" are accepted
    /// \param networkInterface Defines the network interface to use when multiple are present.
    ///        A value of 0 or LOCALHOST_IP_ADDRESS will result in local searches only.
    ///        Values other than this will have firewall implications.
    aLIBEXPORT void __stdcall module_findModule(
        unsigned int* id,
        struct Result* result,
        struct linkSpec_CCA* spec,
        unsigned int serialNumber,
        unsigned int networkInterface,
        int transport);

    /// Disconnects device, but does not destroy underlying object. 
    /// i.e. "module_reconnect" could be called without calling "module_createStem" again.
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    aLIBEXPORT void __stdcall module_disconnect(unsigned int* id, struct Result* result);

    /// Connects to specified sem. 
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    /// \param serialNumber Specify a serial number to connect to a specific
    /// link module. Use 0 to connect to the first link module found.
    aLIBEXPORT void __stdcall module_connect(unsigned int* id, struct Result* result, unsigned int serialNumber);

    /// Reestablishes a connection with a preexisting stem object.  The original stem 
    /// would of been created with "module_createStem".
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    aLIBEXPORT void __stdcall module_reconnect(unsigned int* id, struct Result* result);

    /// Establishes connection through another stems link/connection (i.e. transport: USB, TCPIP).
    /// Refer to BrainStem Networking at www.acroname.com/support
    /// \param id ID assigned through "module_createStem"
    /// \param id_linkStem The link stem's id assigned through "module_createStem"
    ///                   (The stem providing the connection.)
    /// \param result object, containing NO_ERROR or a non zero Error code.
    aLIBEXPORT void __stdcall module_connectThroughLinkModule(unsigned int* id, unsigned int* id_linkStem, struct Result* result);

    /// Changes the module address of the stem object that was created via "module_createStem".
    /// Refer to BrainStem Networking at www.acroname.com/support
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    /// \param address New address to be set.
    aLIBEXPORT void __stdcall module_setModuleAddress(unsigned int* id, struct Result* result, int address);

    /// Retrieves the module address of the stem object that was created via "module_createStem".
    /// Refer to BrainStem Networking at www.acroname.com/support
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR and the module/stems current module address
    ///        or a non zero Error code. 
    aLIBEXPORT void __stdcall module_getModuleAddress(unsigned int* id, struct Result* result);

    /// Returns the current state of the module/stem's connection.
    /// Refer to BrainStem Networking at www.acroname.com/support
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR and the status of the connection
    ///        or a non zero Error code. (0 = disconnected; 1 = connected.)
    aLIBEXPORT void __stdcall module_isConnected(unsigned int* id, struct Result* result);

    /// Check the status of the module connection.
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR and the current status or a non zero Error code.
    /// See aLink.h for linkStatus
    aLIBEXPORT void __stdcall module_getStatus(unsigned int* id, struct Result* result);

    /// Changes the networking mode of the stem object.  Auto mode is enabled by default
    /// which allows automatic adjustment of the module/stems networking configuration.
    /// Refer to BrainStem Networking at www.acroname.com/support
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    /// \param mode New mode to be set.
    aLIBEXPORT void __stdcall module_setNetworkingMode(unsigned int* id, struct Result* result, int mode);

    /// Gets the links current aEther configuration
    /// \param id ID assigned through "module_createStem"
    /// \param result Object containing aErrNone on success.
    /// \param config configuration to be filled upon success.
    aLIBEXPORT void __stdcall module_getAetherConfig(unsigned int* id, struct Result* result, struct aEtherConfig_CCA* config);

    /// Sets the links aEther configuration.
    /// \param id ID assigned through "module_createStem"
    /// \param result object, containing NO_ERROR or a non zero Error code.
    /// \param config configuration to be applied to the link.
    aLIBEXPORT void __stdcall module_setAetherConfig(unsigned int* id, struct Result* result, struct aEtherConfig_CCA* config);

    /// Populates a list with all of the available IPv4 Interfaces.
    /// \param result Object containing aErrNone and the list length upon success
    /// \param buffer List of interfaces found.
    /// \param bufferLength Length of the buffer
    aLIBEXPORT void __stdcall module_GetIPv4Interfaces(struct Result* result, unsigned int* buffer, unsigned int bufferLength);

    /// Disconnects and destroys all modules/stems. During development the dll doesn't always 
    /// "detach" between runs.  This can create problematic scenarios if there are not subsequent 
    /// disconnect and destroy calls for every create call made. This function can be a helpful 
    /// post-execution/tear-down process when bringing up new BrainStem Networks. However, not 
    /// required if connections are handles correctly.
    /// Refer to BrainStem Networking at www.acroname.com/support
    aLIBEXPORT void __stdcall module_clearAllStems();

    /// Get the modules firmware build number
    /// The build number is a unique hash assigned to a specific firmware.
    /// \param id ID assigned through "module_createStem"
    /// \param result Object containing aErrNone and the requested value on success.
    /// Non-zero error code on failure.
    aLIBEXPORT void __stdcall module_getBuild(unsigned int* id, struct Result* result);

    /// Queries the module to determine if it implements a UEI. Each
    /// UEI has a command, option or variant, index and flag. The hasUEI method
    /// queries for a fully specified UEI.
    /// Returns aErrNone if the variation is supported and an appropriate error
    /// if not. This call is blocking for up to the nMSTimeout period.
    /// \param command One of the UEI commands (cmdXXX).
    /// \param option The option or variant of the command.
    /// \param index The entity index.
    /// \param flags The flags (ueiOPTION_SET or ueiOPTION_GET).
    /// \details ::aErrNone - The module supports this command and access flags.
    /// \details ::aErrMode - The module supports the command but not the access flag.
    /// \details ::aErrNotFound - The module does not support the command, option, or index.
    /// \details ::aErrTimeout - The request timed out without a response.
    /// \details ::aErrConnection - There is no active link
     aLIBEXPORT void __stdcall module_hasUEI(unsigned int* id, struct Result* result, unsigned char command, unsigned char option, unsigned char index, unsigned char flags);

    /// Queries the module to determine how many entities of the specified
    /// class are implemented by the module. Zero is a valid return value.
    /// For example, calling classQuantity with the command parameter of
    /// cmdANALOG would return the number of analog entities implemented by the module.
    /// \param id ID assigned through "module_createStem"
    /// \param result Object containing aErrNone and the requested value on success.
    /// \param command One of UEI commands (cmdXXX).
    /// \details ::aErrNone - Success.
    /// \details ::aErrTimeout - The request timed out without a response.
    /// \details ::aErrConnection - There is no active link.
    aLIBEXPORT void __stdcall module_classQuantity(unsigned int* id, struct Result* result, unsigned char command);

    /// Queries the module to determine how many subclass entities of the specified
    /// class are implemented by the module for a given entity index. This is used
    /// for entities which may be 2-dimensional. E.g. cmdMUX subclasses are the number
    /// of channels supported by a particular mux type (index); as a specific example,
    /// a module may support 4 UART channels, so subClassQuantity(cmdMUX, aMUX_UART...)
    /// could return 4.
    /// Zero is a valid return value.
    /// \param id ID assigned through "module_createStem"
    /// \param result Object containing aErrNone and the requested value on success.
    /// \param command One of the UEI commands (cmdXXX).
    /// \param index The entity index.
    /// \details ::aErrNone - Success.
    /// \details ::aErrTimeout - The request timed out waiting for response.
    /// \details ::aErrConnection - There is no active link.
    aLIBEXPORT void __stdcall module_subClassQuantity(unsigned int* id, struct Result* result, unsigned char command, unsigned char index);

    /// Queries the module the group assigned to an entity and index. Entities groups
    /// are used to specify when certain hardware features are fundamentally related. E.g.
    /// certain hardware modules may have some digital pins associated with an adjustable
    /// voltage rail; these digitals would be in the same group as the rail.
    /// Zero is the default group.
    /// \param id ID assigned through "module_createStem"
    /// \param result Object containing aErrNone and the requested value on success.
    /// \param command One of the UEI commands (cmdXXX).
    /// \param index The entity index.
    /// \details ::aErrNone - Success.
    /// \details ::aErrTimeout - The request timed out without response.
    /// \details ::aErrConnection - There is no active link.
    aLIBEXPORT void __stdcall module_entityGroup(unsigned int* id, struct Result* result, unsigned char command, unsigned char index);

#ifdef __cplusplus
}
#endif

#endif
