/*
 * 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

#if defined(CONFIG_HTTP_SERVER) && defined(CONFIG_WEBSOCKET)
	if (ctx->websocket.pending) {
		net_pkt_unref(ctx->websocket.pending);
		ctx->websocket.pending = NULL;
	}

	ctx->websocket.data_waiting = 0;
#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;
}

static inline struct net_pkt *get_net_pkt(struct http_ctx *ctx,
					  const struct sockaddr *dst)
{
	if (!dst) {
		return net_app_get_net_pkt(&ctx->app_ctx, AF_UNSPEC,
					   ctx->timeout);
	}

	return net_app_get_net_pkt_with_dst(&ctx->app_ctx, dst, ctx->timeout);
}

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

	do {
		if (!ctx->pending) {
			ctx->pending = get_net_pkt(ctx, dst);
			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,
		    const struct sockaddr *dst, 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),
				    dst, user_send_data);
	if (ret < 0) {
		return ret;
	}

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

	ret = http_prepare_and_send(ctx, HTTP_CRLF, sizeof(HTTP_CRLF) - 1, dst,
				    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,
			    const struct sockaddr *dst,
			    void *user_send_data)
{
	int ret;

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

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

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

out:
	return ret;
}

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

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