/*
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#if 1
#define SYS_LOG_DOMAIN "https-client"
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
#define NET_LOG_ENABLED 1
#endif

#include <zephyr.h>
#include <errno.h>

#include <net/net_core.h>
#include <net/net_ip.h>

#include <net/http.h>

#include <net/net_app.h>

#include "config.h"

#define INSTANCE_INFO "Zephyr HTTPS example client #1"

#define MAX_ITERATIONS	20
#define WAIT_TIME (APP_REQ_TIMEOUT * 2)

#define RESULT_BUF_SIZE 2048
static u8_t result[RESULT_BUF_SIZE];

/* Note that each HTTPS context needs its own stack as there will be
 * a separate thread for each HTTPS context.
 */
NET_STACK_DEFINE(HTTPS_CLIENT, https_stack,
		 CONFIG_HTTPS_STACK_SIZE, CONFIG_HTTPS_STACK_SIZE);

#define RX_FIFO_DEPTH 4
K_MEM_POOL_DEFINE(ssl_rx_pool, 4, 64, RX_FIFO_DEPTH, 4);

/*
 * Note that the http_client_ctx is quite large so be careful if that is
 * allocated from stack.
 */
static struct http_client_ctx https_ctx;

#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
NET_PKT_TX_SLAB_DEFINE(http_cli_tls_tx, 15);
NET_PKT_DATA_POOL_DEFINE(http_cli_tls_data, 30);

static struct k_mem_slab *tx_slab(void)
{
	return &http_cli_tls_tx;
}

static struct net_buf_pool *data_pool(void)
{
	return &http_cli_tls_data;
}
#else
#if defined(CONFIG_NET_L2_BT)
#error "TCP connections over Bluetooth need CONFIG_NET_CONTEXT_NET_PKT_POOL "\
	"defined."
#endif /* CONFIG_NET_L2_BT */

#define tx_slab NULL
#define data_pool NULL
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */

struct waiter {
	struct http_client_ctx *ctx;
	struct k_sem wait;
	size_t total_len;
	size_t header_len;
};

#include "test_certs.h"

void panic(const char *msg)
{
	if (msg) {
		NET_ERR("%s", msg);
	}

	for (;;) {
		k_sleep(K_FOREVER);
	}
}

/* Load the certificates etc. In this sample app, we verify that
 * the server is the test server we are communicating against to.
 */
static int setup_cert(struct http_client_ctx *ctx, void *cert)
{
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
	mbedtls_ssl_conf_psk(&ctx->https.mbedtls.conf,
			     client_psk, sizeof(client_psk),
			     (const unsigned char *)client_psk_id,
			     sizeof(client_psk_id) - 1);
#endif

#if defined(MBEDTLS_X509_CRT_PARSE_C)
	{
		mbedtls_x509_crt *ca_cert = cert;
		int ret;

		ret = mbedtls_x509_crt_parse_der(ca_cert,
						 ca_certificate,
						 sizeof(ca_certificate));
		if (ret != 0) {
			NET_ERR("mbedtls_x509_crt_parse_der failed "
				"(-0x%x)", -ret);
			return ret;
		}

		mbedtls_ssl_conf_ca_chain(&ctx->https.mbedtls.conf,
					  ca_cert, NULL);
		mbedtls_ssl_conf_authmode(&ctx->https.mbedtls.conf,
					  MBEDTLS_SSL_VERIFY_REQUIRED);

		mbedtls_ssl_conf_cert_profile(&ctx->https.mbedtls.conf,
					    &mbedtls_x509_crt_profile_default);
	}
#endif /* MBEDTLS_X509_CRT_PARSE_C */

	return 0;
}

static int do_sync_http_req(struct http_client_ctx *ctx,
			    enum http_method method,
			    const char *url,
			    const char *content_type,
			    const char *payload)
{
	struct http_client_request req = {};
	int ret;

	req.method = method;
	req.url = url;
	req.protocol = " " HTTP_PROTOCOL HTTP_CRLF;

	ret = http_client_send_req(ctx, &req, NULL, result, sizeof(result),
				   NULL, APP_REQ_TIMEOUT);
	if (ret < 0) {
		NET_ERR("Cannot send %s request (%d)", http_method_str(method),
			ret);
		goto out;
	}

	if (ctx->rsp.data_len > sizeof(result)) {
		NET_ERR("Result buffer overflow by %zd bytes",
		       ctx->rsp.data_len - sizeof(result));

		ret = -E2BIG;
	} else {
		NET_INFO("HTTP server response status: %s",
			 ctx->rsp.http_status);

		if (ctx->parser.http_errno) {
			if (method == HTTP_OPTIONS) {
				/* Ignore error if OPTIONS is not found */
				goto out;
			}

			NET_INFO("HTTP parser status: %s",
			       http_errno_description(ctx->parser.http_errno));
			ret = -EINVAL;
			goto out;
		}

		/* Our example server does not support OPTIONS so check that
		 * here too.
		 */
		if (method != HTTP_HEAD && method != HTTP_OPTIONS) {
			if (ctx->rsp.body_found) {
				NET_INFO("HTTP body: %zd bytes, "
					 "expected: %zd bytes",
					 ctx->rsp.processed,
					 ctx->rsp.content_length);
			} else {
				NET_ERR("Error detected during HTTP msg "
					"processing");
			}
		}
	}

out:
	return ret;
}

void response(struct http_client_ctx *ctx,
	      u8_t *data, size_t buflen,
	      size_t datalen,
	      enum http_final_call data_end,
	      void *user_data)
{
	struct waiter *waiter = user_data;
	int ret;

	if (data_end == HTTP_DATA_MORE) {
		NET_INFO("Received %zd bytes piece of data", datalen);

		/* Do something with the data here. For this example
		 * we just ignore the received data.
		 */
		waiter->total_len += datalen;

		if (ctx->rsp.body_start) {
			/* This fragment contains the start of the body
			 * Note that the header length is not proper if
			 * the header is spanning over multiple recv
			 * fragments.
			 */
			waiter->header_len = ctx->rsp.body_start -
				ctx->rsp.response_buf;
		}

		return;
	}

	waiter->total_len += datalen;

	NET_INFO("HTTP server response status: %s", ctx->rsp.http_status);

	if (ctx->parser.http_errno) {
		if (ctx->req.method == HTTP_OPTIONS) {
			/* Ignore error if OPTIONS is not found */
			goto out;
		}

		NET_INFO("HTTP parser status: %s",
			 http_errno_description(ctx->parser.http_errno));
		ret = -EINVAL;
		goto out;
	}

	if (ctx->req.method != HTTP_HEAD && ctx->req.method != HTTP_OPTIONS) {
		if (ctx->rsp.body_found) {
			NET_INFO("HTTP body: %zd bytes, expected: %zd bytes",
				 ctx->rsp.processed, ctx->rsp.content_length);
		} else {
			NET_ERR("Error detected during HTTP msg processing");
		}

		if (waiter->total_len !=
		    waiter->header_len + ctx->rsp.content_length) {
			NET_ERR("Error while receiving data, "
				"received %zd expected %zd bytes",
				waiter->total_len, waiter->header_len +
				ctx->rsp.content_length);
		}
	}

out:
	k_sem_give(&waiter->wait);
}

static int do_async_http_req(struct http_client_ctx *ctx,
			     enum http_method method,
			     const char *url,
			     const char *content_type,
			     const char *payload)
{
	struct http_client_request req = {};
	struct waiter waiter;
	int ret;

	req.method = method;
	req.url = url;
	req.protocol = " " HTTP_PROTOCOL HTTP_CRLF;

	k_sem_init(&waiter.wait, 0, 1);

	waiter.total_len = 0;

	ret = http_client_send_req(ctx, &req, response, result, sizeof(result),
				   &waiter, APP_REQ_TIMEOUT);
	if (ret < 0 && ret != -EINPROGRESS) {
		NET_ERR("Cannot send %s request (%d)", http_method_str(method),
			ret);
		goto out;
	}

	if (k_sem_take(&waiter.wait, WAIT_TIME)) {
		NET_ERR("Timeout while waiting HTTP response");
		http_client_release(ctx);
		ret = -ETIMEDOUT;
		goto out;
	}

	ret = 0;

out:
	return ret;
}

static inline int do_sync_reqs(struct http_client_ctx *ctx, int count)
{
	int ret;

	/* These examples use the HTTP client API synchronously so they
	 * do not set the callback parameter.
	 */
	while (count--) {
		ret = do_sync_http_req(ctx, HTTP_GET, "/index.html",
				       NULL, NULL);
		if (ret < 0) {
			goto out;
		}

		ret = do_sync_http_req(ctx, HTTP_HEAD, "/",
				       NULL, NULL);
		if (ret < 0) {
			goto out;
		}

		ret = do_sync_http_req(ctx, HTTP_OPTIONS, "/index.html",
				       NULL, NULL);
		if (ret < 0) {
			goto out;
		}

		ret = do_sync_http_req(ctx, HTTP_POST, "/post_test.php",
				       POST_CONTENT_TYPE, POST_PAYLOAD);
		if (ret < 0) {
			goto out;
		}

		/* Note that we cannot receive data bigger than RESULT_BUF_SIZE
		 * if we wait the buffer synchronously. If you want to receive
		 * bigger data, then you need to set the callback when sending
		 * the HTTP request using http_client_send_req()
		 */
	}

out:
	return ret;
}

static inline int do_async_reqs(struct http_client_ctx *ctx, int count)
{
	int ret;

	/* These examples use the HTTP client API asynchronously so they
	 * do set the callback parameter.
	 */
	while (count--) {
		ret = do_async_http_req(ctx, HTTP_GET, "/index.html",
					NULL, NULL);
		if (ret < 0) {
			goto out;
		}

		ret = do_async_http_req(ctx, HTTP_HEAD, "/",
					NULL, NULL);
		if (ret < 0) {
			goto out;
		}

		ret = do_async_http_req(ctx, HTTP_OPTIONS, "/index.html",
					NULL, NULL);
		if (ret < 0) {
			goto out;
		}

		ret = do_async_http_req(ctx, HTTP_POST, "/post_test.php",
					POST_CONTENT_TYPE, POST_PAYLOAD);
		if (ret < 0) {
			goto out;
		}

		/* FIXME: There is a mbedtls SSL buffer size issue if we try to
		 * receive large amount of data. So disable the big-file.html
		 * fetch for time being.
		 */
		if (0) {
			ret = do_async_http_req(ctx, HTTP_GET,
						"/big-file.html",
						NULL, NULL);
			if (ret < 0) {
				goto out;
			}
		}
	}

out:
	return ret;
}

void main(void)
{
	bool failure = false;
	int ret;

	ret = https_client_init(&https_ctx, SERVER_ADDR, SERVER_PORT,
				(u8_t *)INSTANCE_INFO, strlen(INSTANCE_INFO),
				setup_cert, HOSTNAME, NULL, &ssl_rx_pool,
				https_stack, sizeof(https_stack));
	if (ret < 0) {
		NET_ERR("HTTPS init failed (%d)", ret);
		panic(NULL);
	}

	http_client_set_net_pkt_pool(&https_ctx, tx_slab, data_pool);

	ret = do_sync_reqs(&https_ctx, MAX_ITERATIONS);
	if (ret < 0) {
		failure = true;
	}

	ret = do_async_reqs(&https_ctx, MAX_ITERATIONS);
	if (ret < 0) {
		failure = true;
	}

	if (failure) {
		NET_ERR("Some of the tests failed.");
		goto out;
	}

out:
	http_client_release(&https_ctx);

	NET_INFO("Done!");
}
