/**
 * Copyright © 2023 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <errno.h>
#include <err.h>
#include <string.h>
#include <sys/socket.h>

#include "console-server.h"
#include "config.h"

/* size of the dbus object path length */
const size_t dbus_obj_path_len = 1024;

#define DBUS_ERR    "org.openbmc.error"
#define DBUS_NAME   "xyz.openbmc_project.Console.%s"
#define OBJ_NAME    "/xyz/openbmc_project/console/%s"
#define UART_INTF   "xyz.openbmc_project.Console.UART"
#define ACCESS_INTF "xyz.openbmc_project.Console.Access"

static void tty_change_baudrate(struct console *console)
{
	int i;
	int rc;

	tty_init_termios(console->server);

	for (i = 0; i < console->n_handlers; i++) {
		const struct handler_type *type;
		struct handler *handler;

		handler = console->handlers[i];
		type = handler->type;
		if (!type->baudrate) {
			continue;
		}

		rc = type->baudrate(handler, console->server->tty.uart.baud);
		if (rc) {
			warnx("Can't set terminal baudrate for handler %s",
			      type->name);
		}
	}
}

static int set_baud_handler(sd_bus *bus, const char *path,
			    const char *interface, const char *property,
			    sd_bus_message *msg, void *userdata,
			    sd_bus_error *err __attribute__((unused)))
{
	struct console *console = userdata;
	uint64_t baudrate;
	speed_t speed;
	int r;

	if (!console) {
		return -ENOENT;
	}

	r = sd_bus_message_read(msg, "t", &baudrate);
	if (r < 0 || baudrate > UINT32_MAX) {
		return -EINVAL;
	}

	speed = parse_int_to_baud((uint32_t)baudrate);
	if (!speed) {
		warnx("Invalid baud rate: '%" PRIu64 "'", baudrate);
		return -EINVAL;
	}

	assert(console->server->tty.type == TTY_DEVICE_UART);
	console->server->tty.uart.baud = speed;
	tty_change_baudrate(console);

	sd_bus_emit_properties_changed(bus, path, interface, property, NULL);

	return 1;
}

static int get_baud_handler(sd_bus *bus __attribute__((unused)),
			    const char *path __attribute__((unused)),
			    const char *interface __attribute__((unused)),
			    const char *property __attribute__((unused)),
			    sd_bus_message *reply, void *userdata,
			    sd_bus_error *error __attribute__((unused)))
{
	struct console *console = userdata;
	struct console_server *server = console->server;
	uint64_t baudrate;
	int r;

	assert(server->tty.type == TTY_DEVICE_UART);
	baudrate = parse_baud_to_int(server->tty.uart.baud);
	if (!baudrate) {
		warnx("Invalid baud rate: '%d'", server->tty.uart.baud);
	}

	r = sd_bus_message_append(reply, "t", baudrate);

	return r;
}

static int method_connect(sd_bus_message *msg, void *userdata,
			  sd_bus_error *err)
{
	struct console *console = userdata;
	int rc;
	int socket_fd = -1;

	if (!console) {
		warnx("Internal error: Console pointer is null");
		sd_bus_error_set_const(err, DBUS_ERR, "Internal error");
		return sd_bus_reply_method_error(msg, err);
	}

	/* Register the consumer. */
	socket_fd = dbus_create_socket_consumer(console);
	if (socket_fd < 0) {
		rc = socket_fd;
		warnx("Failed to create socket consumer: %s", strerror(rc));
		sd_bus_error_set_const(err, DBUS_ERR,
				       "Failed to create socket consumer");
		return sd_bus_reply_method_error(msg, err);
	}

	rc = sd_bus_reply_method_return(msg, "h", socket_fd);

	/* Close the our end */
	close(socket_fd);

	return rc;
}

static const sd_bus_vtable console_uart_vtable[] = {
	SD_BUS_VTABLE_START(0),
	SD_BUS_WRITABLE_PROPERTY("Baud", "t", get_baud_handler,
				 set_baud_handler, 0,
				 SD_BUS_VTABLE_UNPRIVILEGED |
					 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
	SD_BUS_VTABLE_END,
};

static const sd_bus_vtable console_access_vtable[] = {
	SD_BUS_VTABLE_START(0),
	SD_BUS_METHOD("Connect", SD_BUS_NO_ARGS, "h", method_connect,
		      SD_BUS_VTABLE_UNPRIVILEGED),
	SD_BUS_VTABLE_END,
};

int dbus_init(struct console *console,
	      struct config *config __attribute__((unused)))
{
	char obj_name[dbus_obj_path_len];
	char dbus_name[dbus_obj_path_len];
	int dbus_poller = 0;
	int fd;
	int r;
	size_t bytes;

	if (!console) {
		warnx("Couldn't get valid console");
		return -1;
	}

	r = sd_bus_default(&console->bus);
	if (r < 0) {
		warnx("Failed to connect to bus: %s", strerror(-r));
		return -1;
	}

	/* Register support console interface */
	bytes = snprintf(obj_name, dbus_obj_path_len, OBJ_NAME,
			 console->console_id);
	if (bytes >= dbus_obj_path_len) {
		warnx("Console id '%s' is too long. There is no enough space in the buffer.",
		      console->console_id);
		return -1;
	}

	if (console->server->tty.type == TTY_DEVICE_UART) {
		/* Register UART interface */
		r = sd_bus_add_object_vtable(console->bus, NULL, obj_name,
					     UART_INTF, console_uart_vtable,
					     console);
		if (r < 0) {
			warnx("Failed to register UART interface: %s",
			      strerror(-r));
			return -1;
		}
	}

	/* Register access interface */
	r = sd_bus_add_object_vtable(console->bus, NULL, obj_name, ACCESS_INTF,
				     console_access_vtable, console);
	if (r < 0) {
		warnx("Failed to issue method call: %s", strerror(-r));
		return -1;
	}

	bytes = snprintf(dbus_name, dbus_obj_path_len, DBUS_NAME,
			 console->console_id);
	if (bytes >= dbus_obj_path_len) {
		warnx("Console id '%s' is too long. There is no enough space in the buffer.",
		      console->console_id);
		return -1;
	}

	/* Finally register the bus name */
	r = sd_bus_request_name(console->bus, dbus_name,
				SD_BUS_NAME_ALLOW_REPLACEMENT |
					SD_BUS_NAME_REPLACE_EXISTING);
	if (r < 0) {
		warnx("Failed to acquire service name: %s", strerror(-r));
		return -1;
	}

	fd = sd_bus_get_fd(console->bus);
	if (fd < 0) {
		warnx("Couldn't get the bus file descriptor");
		return -1;
	}

	dbus_poller = POLLFD_DBUS;

	console->pollfds[dbus_poller].fd = fd;
	console->pollfds[dbus_poller].events = POLLIN;

	return 0;
}
