// ----------------------------------------------------------------------------
// Copyright 2016-2017 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------

#ifndef ARM_UPDATE_CLIENT_HUB_H
#define ARM_UPDATE_CLIENT_HUB_H

#include "update-client-common/arm_uc_types.h"
#include "update-client-source/arm_uc_source.h"
#include "update-client-monitor/arm_uc_monitor.h"
#include "update-client-control-center/arm_uc_control_center.h"
#include "update-client-paal/arm_uc_paal_update.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Initialization return codes.
 */
enum {
    ARM_UC_INIT_DONE
};

/**
 * @brief Start the initialization of the hub.
 * @details When initilisation finishes, the user callback function
 *          will be called. The "event" parameter to the callback
 *          is currently a placeholder that always returns ARM_UC_INIT_DONE.
 *
 * @param  function to be called when initilisation is finished.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_HUB_Initialize(void (*callback)(uintptr_t));

/**
 * @brief Process events in the event queue.
 * @details The update client is driven by events in an atomic queue,
 *          the user need to call this function periodically to process
 *          events in the queue and hence move the client forward.
 *
 * @return Error code.
 * @note Here's a code snippet to suggest how this API might be used by callers:
 * \code
 * int main() {
 *     retval = ARM_UC_Hub.Initialize(init_finish_cb);
 *     while(true) {
 *         ARM_UC_Hub.ProcessEvents();
 *         __WFI();
 *     }
 * }
 * \endcode
 */
arm_uc_error_t ARM_UC_HUB_ProcessEvents(void);

/**
 * @brief Register callback function for when callbacks are added to an
 *        empty queue.
 * @details This function is called at least once (maybe more) when
 *          callbacks are added to an empty queue. Useful for scheduling
 *          when the queue needs to be processed.
 * @param handler Function pointer to function to be called when elements are
 *        added to an empty queue.
 */
arm_uc_error_t ARM_UC_HUB_AddNotificationHandler(void (*handler)(void));

/**
 * @brief Add sources to the update client.
 * @details Sources are transport methods for manifest and firmwares.
 *
 * @param sources Pointer to an array of source pointers.
 * @param size Number of elements in the pointer array.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_HUB_SetSources(const ARM_UPDATE_SOURCE *sources[],
                                     uint8_t size);

/**
 * @brief Set implementation for storing firmware.
 * @details Storage abstraction for handling different storage medium.
 *
 * @param implementation Function pointer struct to Update PAL implementation.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_HUB_SetStorage(const ARM_UC_PAAL_UPDATE *implementation);

/**
 * @brief Add monitor to the update client.
 * @details Monitors send the update status and results.
 *
 * @param  monitor The monitor to be added to the update client.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_HUB_AddMonitor(const ARM_UPDATE_MONITOR *monitor);

/**
 * @brief Temporary error reporting function.
 * @details This function will be absorbed into the add monitor call.
 *
 * @param callback Error reporting function.
 */
void ARM_UC_HUB_AddErrorCallback(void (*callback)(int32_t error));

/**
 * @brief Authorize request.
 * @details Function is called when the user application authorizes
 *          requests from the Update Client.
 *
 * @param request Requests are passed through the callback function.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_Authorize(arm_uc_request_t request);

/**
 * @brief Reject request.
 * @details Function is called when the user application rejects
 *          requests from the Update Client.
 *
 * @param request Requests are passed through the callback function.
 * @param reason Reason for rejecting the request.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_Reject(arm_uc_request_t request, arm_uc_reject_reason_t reason);

/**
 * @brief Set callback for receiving download progress.
 * @details User application call for setting callback handler.
 *          The callback function takes the progreess in percent as argument.
 *
 * @param callback Function pointer to the progress function.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_SetProgressHandler(void (*callback)(uint32_t progress, uint32_t total));

/**
 * @brief Set callback function for authorizing requests without specific priority.
 * @details User application call for setting callback handler.
 *          The callback function takes an enum request and an authorization
 *          function pointer. To authorize the given request, the caller
 *          invokes the authorization function.
 *
 * @param callback Function pointer to the authorization function.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_SetAuthorizeHandler(void (*callback)(int32_t)) __attribute__((deprecated("Use ARM_UC_SetAuthorizePriorityHandler instead")));

/**
 * @brief Set callback function for authorizing requests with specific priority.
 * @details User application call for setting callback handler.
 *          The callback function takes an enum request, an authorization
 *          function pointer and a priority value. To authorize the given
 *          request, the caller invokes the authorization function.
 *
 * @param callback Function pointer to the authorization function.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_SetAuthorizePriorityHandler(void (*callback)(int32_t request, uint64_t priority));

/**
 * @brief Override update authorization handler.
 * @details Force download and update to progress regardless of authorization
 *          handler. This function is used for unblocking an update in a buggy
 *          application.
 */
void ARM_UC_OverrideAuthorization(void);

/**
 * @brief Add certificate.
 * @details [long description]
 *
 * @param certificate Pointer to certiface being added.
 * @param certificate_length Certificate length.
 * @param fingerprint Pointer to the fingerprint of the certificate being added.
 * @param fingerprint_length Fingerprint length.
 * @param callback Callback handler for certificate insertion events.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_AddCertificate(const uint8_t *certificate,
                                     uint16_t certificate_length,
                                     const uint8_t *fingerprint,
                                     uint16_t fingerprint_length,
                                     void (*callback)(arm_uc_error_t, const arm_uc_buffer_t *));

/**
 * @brief Set pointer to pre-shared-key with the given size.
 *
 * @param key Pointer to pre-shared-key.
 * @param bits Key size in bits.
 *
 * @return Error code.
 */
arm_uc_error_t ARM_UC_AddPreSharedKey(const uint8_t *key, uint16_t bits);

/**
 * @brief Function for setting the vendor ID.
 * @details The ID is copied to a 16 byte struct. Any data after the first
 *          16 bytes will be ignored.
 * @param id Pointer to ID.
 * @param length Length of ID.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_SetVendorId(const uint8_t *id, uint8_t length);

/**
 * @brief Function for setting the class ID.
 * @details The ID is copied to a 16 byte struct. Any data after the first
 *          16 bytes will be ignored.
 * @param id Pointer to ID.
 * @param length Length of ID.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_SetClassId(const uint8_t *id, uint8_t length);

/**
 * @brief Function for setting the device ID.
 * @details The ID is copied to a 16 byte struct. Any data after the first
 *          16 bytes will be ignored.
 * @param id Pointer to ID.
 * @param length Length of ID.
 * @return Error code.
 */
arm_uc_error_t ARM_UC_SetDeviceId(const uint8_t *id, uint8_t length);

/**
 * @brief Function for reporting the vendor ID.
 * @details 16 bytes are copied into the supplied buffer.
 * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
 * @param id_max the size of the ID buffer
 * @param id_size pointer to a variable to receive the size of the ID
 *                written into the buffer (always 16).
 * @return Error code.
 */
arm_uc_error_t ARM_UC_GetVendorId(uint8_t *id,
                                  const size_t id_max,
                                  size_t *id_size);

/**
 * @brief Function for reporting the class ID.
 * @details 16 bytes are copied into the supplied buffer.
 * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
 * @param id_max the size of the ID buffer
 * @param id_size pointer to a variable to receive the size of the ID
 *                written into the buffer (always 16).
 * @return Error code.
 */
arm_uc_error_t ARM_UC_GetClassId(uint8_t *id,
                                 const size_t id_max,
                                 size_t *id_size);

/**
 * @brief Function for reporting the device ID.
 * @details 16 bytes are copied into the supplied buffer.
 * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
 * @param id_max the size of the ID buffer
 * @param id_size pointer to a variable to receive the size of the ID
 *                written into the buffer (always 16).
 * @return Error code.
 */
arm_uc_error_t ARM_UC_GetDeviceId(uint8_t *id,
                                  const size_t id_max,
                                  size_t *id_size);


/**
 * @brief Delete any global allocations.
 */
arm_uc_error_t ARM_UC_HUB_Uninitialize(void);

/**
 * @brief Return the details of the active firmware.
 * @param details Pointer to the firmware details structure.
 * @return ARM_UC_HUB_ERR_NOT_AVAILABLE if the active firmware details
 *         are not yet available, ERR_INVALID_PARAMETER if "details" is
 *         NULL or ERR_NONE for success.
 */
arm_uc_error_t ARM_UC_API_GetActiveFirmwareDetails(arm_uc_firmware_details_t *details);

#ifdef __cplusplus
}
#endif

#endif /* ARM_UPDATE_CLIENT_HUB_H */
