/*
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL). See the LICENSE file in the root
 * directory for license terms. You may choose either license, or both.
 */

#ifndef STORAGE_DISPATCHER_PRIVATE_H
#define STORAGE_DISPATCHER_PRIVATE_H


#include "iotcs.h"
#include "advanced/iotcs_storage_object.h"
#include "iotcs_storage_object.h"
#include "protocol/protocol_request.h"
#include "device_model/device_model_private.h"
#include "iotcs_port_queue.h"

#define SCS_IS_SYNCING(sync_status)  (sync_status == IOTCS_INITIATED || sync_status == IOTCS_QUEUED || sync_status == IOTCS_IN_PROGRESS)
#define IS_STORAGE_OBJECT(x) ((x) && (x)->type == IOTCS_STORAGE_OBJECT)
#define IS_EXTERNAL_OBJECT(x) ((x) && (x)->type == IOTCS_EXTERNAL_OBJECT)
/**
 * @brief Common private header
 */

#ifdef __cplusplus
extern "C" {
#endif

#ifndef DISABLE_STORAGE_OBJECT_PREFIX
#define DISABLE_STORAGE_OBJECT_PREFIX 0
#endif

    /**
     * @enum iotcs_log_channel
     * @brief Log channel
     */
    typedef enum {
        IOTCS_UNDEFINED_OBJECT = 0,
        IOTCS_EXTERNAL_OBJECT,
        IOTCS_STORAGE_OBJECT
    } iotcs_uri_object_type;

    /**
     * @struct iotcs_storage_object_t
     * @brief Storage Object structure
     */
    typedef struct sd_storage_object_t {
        const char* name;
        const char* endpoint_id;
        const char* uri;
        const char* input_path;
        const char* output_path;
        const char* content_type;
        const char* encoding;
        uint64_t content_length;
        iotcs_date_time content_date;
        iotcs_storage_object_sync_callback sync_callback;
        iotcs_storage_dispatcher_progress_state progress_state;
        struct iotcs_virtual_device_handle_t* device_handle;
    } sd_storage_object;

    /**
     * @struct iotcs_uri_object_t
     * @brief Common structure with pointer to object and type of object:
     *          - IOTCS_UNDEFINED_OBJECT 
     *          - IOTCS_EXTERNAL_OBJECT then object is char* with URI
     *          - IOTCS_STORAGE_OBJECT then object is struct sd_storage_object_t
     */
    struct iotcs_uri_object_t {
        void *object;
        iotcs_uri_object_type type;
        int ref_cnt;
    };

    typedef struct iotcs_uri_object_t iotcs_storage_object;
    typedef struct iotcs_uri_object_t iotcs_external_object;

    extern iotcs_storage_dispatcher_progress_callback progress_callback;
    extern int g_storage_initialized;

    iotcs_result cl_internal_storage_init();
    void cl_internal_storage_finalize();
    iotcs_result cl_internal_send_download_request_unsafe(iotcs_storage_request* request, protocol_response* response);
    iotcs_result cl_internal_send_upload_request_unsafe(iotcs_storage_request* request, protocol_response* response);
    iotcs_result cl_internal_send_reconfig_request_md();

    iotcs_result cl_storage_object_sync(iotcs_storage_object *storage_object_handle);
    iotcs_bool cl_storage_progress_cb_h(iotcs_storage_object *storage,
            iotcs_storage_dispatcher_progress_state state,
            int64_t bytes_transfered, const char *fail_reason);
    void cl_storage_progress_cb(iotcs_storage_object *storage,
            iotcs_storage_dispatcher_progress_state state,
            int64_t bytes_transfered, const char *fail_reason);
    iotcs_result cl_internal_storage_file_upload(iotcs_storage_request* request);
    iotcs_result cl_internal_storage_file_download(iotcs_storage_request* request);
    iotcs_result cl_internal_storage_dispatcher_queue_safe(iotcs_storage_request* request);
    iotcs_result cl_internal_storage_async_dispatcher_init();
    void cl_internal_storage_async_dispatcher_finalize(void);

    /**
     * @brief IoT CS method to get the content type and length of a file
     *        in secure cloud storage_object.
     * @param storage pointer to #iotcs_storage_object 
     *
     * @retval IOTCS_RESULT_INVALID_ARGUMENT if storage_object is NULL.
     * @retval IOTCS_RESULT_OK if succeeds.
     * @retval IOTCS_RESULT_FAIL otherwise.
     */
    iotcs_result iotcs_storage_object_fill_file_info(iotcs_storage_object* storage_object);
#ifdef __cplusplus
}
#endif

#endif /* STORAGE_DISPATCHER_PRIVATE_H */
