/* 
 * Copyright (c) 2006 - 2018 QIU ZHONG HUAI <huai2011@163.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:

 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes CC software, freely available from
 *    <https://github.com/huai2001/CC/>".
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.

 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */
 #ifndef _C_CC_URL_REQUEST_H_INCLUDED_
#define _C_CC_URL_REQUEST_H_INCLUDED_

#include <cc/url.h>
#include <cc/hashmap.h>
#include <cc/core/event.h>
#include <cc/stream.h>

#ifdef CC_OPENSSL_HTTPS

#endif

/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif

#define CC_URL_REQUEST_OUT_OF_MEMORY                    1
#define CC_URL_REQUEST_HTTP_ERROR                       2
#define CC_URL_REQUEST_INVALID_URL                      3
#define CC_URL_REQUEST_INVALID_HOST                     4
#define CC_URL_REQUEST_SOCKET_FAILED                    5
#define CC_URL_REQUEST_SOCKET_CONNECT_FAILED            6
#define CC_URL_REQUEST_SOCKET_SEND_FAILED               7
#define CC_URL_REQUEST_SOCKET_TIMEOUT                   8
#define CC_URL_REQUEST_HTTPS_ERROR                      9

/************************************************************************/
typedef struct _cc_field_and_value cc_url_params_t;
typedef struct _cc_field_and_value cc_cookie_params_t;
typedef struct _cc_field_and_value cc_http_header_t;
typedef struct _cc_field_and_value cc_field_and_value_t;

typedef struct _cc_url_request cc_url_request_t; 
typedef struct _cc_url_request_callback cc_url_request_callback_t;
typedef struct _cc_url_response_header cc_url_response_header_t;

typedef bool_t (CC_CALL *_cb_url_requset_error_t)(pvoid_t, uint32_t);
typedef bool_t (CC_CALL *_cb_url_requset_success_t)(pvoid_t);
typedef bool_t (CC_CALL *_cb_url_requset_before_send_t)(cc_url_t*, tchar_t*, int32_t*, pvoid_t);
typedef bool_t (CC_CALL *_cb_url_requset_read_t)(pvoid_t, byte_t*, int32_t);
typedef bool_t (CC_CALL *_cb_url_requset_header_t)(cc_url_request_t*, cc_url_response_header_t*);

typedef cc_event_t* (CC_CALL *_cb_url_request_connect_t)(const tchar_t *host, uint16_t port, int32_t timeout, cc_event_callback_t callback, pvoid_t);
/************************************************************************/

/**/
struct _cc_url_request_callback
{
    _cb_url_request_connect_t cb_connect;
    _cb_url_requset_error_t cb_error;
    _cb_url_requset_success_t cb_success;
    _cb_url_requset_before_send_t cb_before_send;
    _cb_url_requset_header_t cb_header;
    _cb_url_requset_read_t cb_read;
    int32_t timeout;
    pvoid_t args;
};

/**/
struct _cc_field_and_value
{
    char_t *name;
    char_t *value;
};

/**/
struct _cc_url_response_header {
    int32_t major;
    int32_t minor;
    int32_t status;
    cc_hmap_t *headers;
};

/**/
struct _cc_url_request
{
    bool_t valid;
    cc_url_t *address;
    cc_event_t *sock_event;

    cc_url_response_header_t *response;
    cc_url_request_callback_t cb;

    uint64_t length;
    uint64_t content_length;

#ifdef CC_OPENSSL_HTTPS
    SSL *ssl;
    SSL_CTX *ssl_ctx;
#endif
};
    
/**/
CC_DECLSPEC(bool_t) cc_url_request(const tchar_t *address, cc_url_request_callback_t *cb);
/**/
CC_DECLSPEC(cc_stream_t*) cc_join_url_params(cc_hmap_t *self, const char_t delimiter);
/**/
CC_DECLSPEC(cc_hmap_t*)  cc_split_url_params(const char_t *str, const char_t delimiter);
/**/
CC_DECLSPEC(bool_t) cc_destroy_url_params(cc_hmap_t** self);
/**/
CC_DECLSPEC(char_t*) cc_url_read_prarms(cc_hmap_t *self, const tchar_t *name);

/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif


#endif /*_C_CC_URL_REQUEST_H_INCLUDED_*/
