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

#if defined(CONFIG_NET_DEBUG_HTTP)
#define SYS_LOG_DOMAIN "http"
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
#define NET_LOG_ENABLED 1
#endif

#include <zephyr.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <stdlib.h>
#include <version.h>
#include <misc/printk.h>

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

int http_set_cb(struct http_ctx *ctx,
		http_connect_cb_t connect_cb,
		http_recv_cb_t recv_cb,
		http_send_cb_t send_cb,
		http_close_cb_t close_cb)
{
	if (!ctx) {
		return -EINVAL;
	}

	if (!ctx->is_init) {
		return -ENOENT;
	}

	ctx->cb.connect = connect_cb;
	ctx->cb.recv = recv_cb;
	ctx->cb.send = send_cb;
	ctx->cb.close = close_cb;

	return 0;
}

int http_close(struct http_ctx *ctx)
{
	if (!ctx) {
		return -EINVAL;
	}

	if (!ctx->is_init) {
		return -ENOENT;
	}

	http_send_flush(ctx, NULL);
	if (ctx->pending) {
		net_pkt_unref(ctx->pending);
		ctx->pending = NULL;
	}

#if defined(CONFIG_HTTP_SERVER) && defined(CONFIG_NET_DEBUG_HTTP_CONN)
	if (!ctx->is_client) {
		http_server_conn_del(ctx);
	}
#endif

	return net_app_close(&ctx->app_ctx);
}

int http_release(struct http_ctx *ctx)
{
	if (!ctx) {
		return -EINVAL;
	}

	if (!ctx->is_init) {
		return -ENOENT;
	}

	ctx->is_tls = false;

#if defined(CONFIG_HTTP_SERVER) && defined(CONFIG_NET_DEBUG_HTTP_CONN)
	if (!ctx->is_client) {
		http_server_conn_del(ctx);
		http_server_disable(ctx);
	}
#endif

	if (ctx->pending) {
		net_pkt_unref(ctx->pending);
		ctx->pending = NULL;
	}

	ctx->is_init = false;

	return net_app_release(&ctx->app_ctx);
}

int http_send_msg_raw(struct http_ctx *ctx, struct net_pkt *pkt,
		      void *user_send_data)
{
	int ret;

	NET_DBG("[%p] Sending %zd bytes data", ctx, net_pkt_get_len(pkt));

	ret = net_app_send_pkt(&ctx->app_ctx, pkt, NULL, 0, 0,
			       user_send_data);
	if (!ret) {
		/* We must let the system to send the packet, otherwise TCP
		 * might timeout before the packet is actually sent. This is
		 * easily seen if the application calls this functions many
		 * times in a row.
		 */
		k_yield();
	}

	return ret;
}

int http_prepare_and_send(struct http_ctx *ctx,
			  const char *payload,
			  size_t payload_len,
			  void *user_send_data)
{
	size_t added;
	int ret;

	do {
		if (!ctx->pending) {
			ctx->pending = net_app_get_net_pkt(&ctx->app_ctx,
							   AF_UNSPEC,
							   ctx->timeout);
			if (!ctx->pending) {
				return -ENOMEM;
			}
		}

		ret = net_pkt_append(ctx->pending, payload_len, payload,
				     ctx->timeout);
		if (!ret || ret > payload_len) {
			ret = -EINVAL;
			goto error;
		}

		added = ret;

		payload_len -= added;
		if (payload_len) {
			payload += added;
			/* Not all data could be added, send what we have now
			 * and allocate new stuff to be sent.
			 */
			ret = http_send_flush(ctx, user_send_data);
			if (ret < 0) {
				goto error;
			}
		}
	} while (payload_len);

	return 0;

error:
	if (ctx->pending) {
		net_pkt_unref(ctx->pending);
		ctx->pending = NULL;
	}

	return ret;
}

int http_send_flush(struct http_ctx *ctx, void *user_send_data)
{
	int ret;

	if (!ctx->pending) {
		return 0;
	}

	ret = http_send_msg_raw(ctx, ctx->pending, user_send_data);
	if (ret < 0) {
		return ret;
	}

	ctx->pending = NULL;

	return ret;
}

int http_send_chunk(struct http_ctx *ctx, const char *buf, size_t len,
		    void *user_send_data)
{
	char chunk_header[16];
	int ret;

	if (!buf) {
		len = 0;
	}

	snprintk(chunk_header, sizeof(chunk_header), "%x" HTTP_CRLF,
		 (unsigned int)len);

	ret = http_prepare_and_send(ctx, chunk_header, strlen(chunk_header),
				    user_send_data);
	if (ret < 0) {
		return ret;
	}

	if (len) {
		ret = http_prepare_and_send(ctx, buf, len, user_send_data);
		if (ret < 0) {
			return ret;
		}
	}

	ret = http_prepare_and_send(ctx, HTTP_CRLF, sizeof(HTTP_CRLF),
				    user_send_data);
	if (ret < 0) {
		return ret;
	}

	return 0;
}

static int _http_add_header(struct http_ctx *ctx, s32_t timeout,
			    const char *name, const char *value,
			    void *user_send_data)
{
	int ret;

	ret = http_prepare_and_send(ctx, name, strlen(name), user_send_data);
	if (value && ret >= 0) {
		ret = http_prepare_and_send(ctx, ": ", strlen(": "),
					    user_send_data);
		if (ret < 0) {
			goto out;
		}

		ret = http_prepare_and_send(ctx, value, strlen(value),
					    user_send_data);
		if (ret < 0) {
			goto out;
		}

		ret = http_prepare_and_send(ctx, HTTP_CRLF, strlen(HTTP_CRLF),
					    user_send_data);
		if (ret < 0) {
			goto out;
		}
	}

out:
	return ret;
}

int http_add_header(struct http_ctx *ctx, const char *field,
		    void *user_send_data)
{
	return _http_add_header(ctx, ctx->timeout, field, NULL, user_send_data);
}

int http_add_header_field(struct http_ctx *ctx, const char *name,
			  const char *value, void *user_send_data)
{
	return _http_add_header(ctx, ctx->timeout, name, value, user_send_data);
}
