/*
 * Copyright (c) 2019 Linaro Limited
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <device.h>

#include <net/socket.h>

#include <drivers/video.h>

#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(main);

#if defined(CONFIG_VIDEO_MCUX_CSI)
#define VIDEO_CAPTURE_DEV DT_LABEL(DT_INST(0, nxp_imx_csi))
#else
#define VIDEO_CAPTURE_DEV "VIDEO_SW_GENERATOR"
#endif

#define MY_PORT 5000
#define MAX_CLIENT_QUEUE 1

static ssize_t sendall(int sock, const void *buf, size_t len)
{
	while (len) {
		ssize_t out_len = send(sock, buf, len, 0);

		if (out_len < 0) {
			return out_len;
		}
		buf = (const char *)buf + out_len;
		len -= out_len;
	}

	return 0;
}

void main(void)
{
	struct sockaddr_in addr, client_addr;
	socklen_t client_addr_len = sizeof(client_addr);
	struct video_buffer *buffers[2], *vbuf;
	int i, ret, sock, client;
	struct video_format fmt;
	const struct device *video;

	/* Prepare Network */
	(void)memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(MY_PORT);

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock < 0) {
		LOG_ERR("Failed to create TCP socket: %d", errno);
		return;
	}

	ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
	if (ret < 0) {
		LOG_ERR("Failed to bind TCP socket: %d", errno);
		close(sock);
		return;
	}

	ret = listen(sock, MAX_CLIENT_QUEUE);
	if (ret < 0) {
		LOG_ERR("Failed to listen on TCP socket: %d", errno);
		close(sock);
		return;
	}

	/* Prepare Video Capture */
	video = device_get_binding(VIDEO_CAPTURE_DEV);
	if (video == NULL) {
		LOG_ERR("Video device %s not found. Aborting test.",
			VIDEO_CAPTURE_DEV);
		return;
	}

	/* Get default/native format */
	if (video_get_format(video, VIDEO_EP_OUT, &fmt)) {
		LOG_ERR("Unable to retrieve video format");
		return;
	}

	printk("Video device detected, format: %c%c%c%c %ux%u\n",
	       (char)fmt.pixelformat, (char)(fmt.pixelformat >> 8),
	       (char)(fmt.pixelformat >> 16), (char)(fmt.pixelformat >> 24),
	       fmt.width, fmt.height);

	/* Alloc Buffers */
	for (i = 0; i < ARRAY_SIZE(buffers); i++) {
		buffers[i] = video_buffer_alloc(fmt.pitch * fmt.height);
		if (buffers[i] == NULL) {
			LOG_ERR("Unable to alloc video buffer");
			return;
		}
	}

	/* Connection loop */
	do {
		printk("TCP: Waiting for client...\n");

		client = accept(sock, (struct sockaddr *)&client_addr,
				&client_addr_len);
		if (client < 0) {
			printk("Failed to accept: %d\n", errno);
			return;
		}

		printk("TCP: Accepted connection\n");

		/* Enqueue Buffers */
		for (i = 0; i < ARRAY_SIZE(buffers); i++) {
			video_enqueue(video, VIDEO_EP_OUT, buffers[i]);
		}

		/* Start video capture */
		if (video_stream_start(video)) {
			LOG_ERR("Unable to start video");
			return;
		}

		printk("Stream started\n");

		/* Capture loop */
		i = 0;
		do {
			ret = video_dequeue(video, VIDEO_EP_OUT, &vbuf,
					    K_FOREVER);
			if (ret) {
				LOG_ERR("Unable to dequeue video buf");
				return;
			}

			printk("\rSending frame %d", i++);

			/* Send video buffer to TCP client */
			ret = sendall(client, vbuf->buffer, vbuf->bytesused);
			if (ret && ret != -EAGAIN) {
				/* client disconnected */
				printk("\nTCP: Client disconnected %d\n", ret);
				close(client);
			}

			(void)video_enqueue(video, VIDEO_EP_OUT, vbuf);
		} while (!ret);

		/* stop capture */
		if (video_stream_stop(video)) {
			LOG_ERR("Unable to stop video");
			return;
		}

		/* Flush remaining buffers */
		do {
			ret = video_dequeue(video, VIDEO_EP_OUT,
					    &vbuf, K_NO_WAIT);
		} while (!ret);

	} while (1);
}
