// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "uartdpi.h"

#ifdef __linux__
#include <pty.h>
#elif __APPLE__
#include <util.h>
#endif

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void *uartdpi_create(const char *name, const char *log_file_path) {
  struct uartdpi_ctx *ctx =
      (struct uartdpi_ctx *)malloc(sizeof(struct uartdpi_ctx));
  assert(ctx);

  int rv;

  // Initialize UART pseudo-terminal
  struct termios tty;
  cfmakeraw(&tty);

  rv = openpty(&ctx->host, &ctx->device, 0, &tty, 0);
  assert(rv != -1);

  rv = ttyname_r(ctx->device, ctx->ptyname, 64);
  assert(rv == 0 && "ttyname_r failed");

  int cur_flags = fcntl(ctx->host, F_GETFL, 0);
  assert(cur_flags != -1 && "Unable to read current flags.");
  int new_flags = fcntl(ctx->host, F_SETFL, cur_flags | O_NONBLOCK);
  assert(new_flags != -1 && "Unable to set FD flags");

  printf(
      "\n"
      "UART: Created %s for %s. Connect to it with any terminal program, e.g.\n"
      "$ screen %s\n",
      ctx->ptyname, name, ctx->ptyname);

  const char *test_out_dir = getenv("TEST_UNDECLARED_OUTPUTS_DIR");
  const int kMaxPathLen = 512;
  if (test_out_dir) {
    char device_file[kMaxPathLen] = {0};
    snprintf(device_file, kMaxPathLen, "%s/%s_device", test_out_dir, name);
    if (symlink(ctx->ptyname, device_file) == 0) {
      printf("Created symlink device %s for %s.\n", device_file, name);
    }
  }

  // Open log file (if requested)
  ctx->log_file = NULL;
  bool write_log_file = strlen(log_file_path) != 0;
  if (write_log_file) {
    if (strcmp(log_file_path, "-") == 0) {
      ctx->log_file = stdout;
      printf("UART: Additionally writing all UART output to STDOUT.\n");

    } else {
      FILE *log_file;
      char test_out_log_file[kMaxPathLen] = {0};
      if (test_out_dir) {
        snprintf(test_out_log_file, kMaxPathLen, "%s/%s", test_out_dir,
                 log_file_path),
            log_file = fopen(test_out_log_file, "w");
      } else {
        log_file = fopen(log_file_path, "w");
      }
      if (!log_file) {
        fprintf(stderr, "UART: Unable to open log file at %s: %s\n",
                test_out_dir ? test_out_log_file : log_file_path,
                strerror(errno));
      } else {
        // Switch log file output to line buffering to ensure lines written to
        // the UART device show up in the log file as soon as a newline
        // character is written.
        rv = setvbuf(log_file, NULL, _IOLBF, 0);
        assert(rv == 0);

        ctx->log_file = log_file;
        printf("UART: Additionally writing all UART output to '%s'.\n",
               test_out_dir ? test_out_log_file : log_file_path);
      }
    }
  }

  return (void *)ctx;
}

void uartdpi_close(void *ctx_void) {
  struct uartdpi_ctx *ctx = (struct uartdpi_ctx *)ctx_void;
  if (!ctx) {
    return;
  }

  close(ctx->host);
  close(ctx->device);

  if (ctx->log_file) {
    // Always ensure the log file is flushed (most important when writing
    // to STDOUT)
    fflush(ctx->log_file);
    if (ctx->log_file != stdout) {
      fclose(ctx->log_file);
    }
  }

  free(ctx);
}

int uartdpi_can_read(void *ctx_void) {
  struct uartdpi_ctx *ctx = (struct uartdpi_ctx *)ctx_void;

  int rv = read(ctx->host, &ctx->tmp_read, 1);
  return (rv == 1);
}

char uartdpi_read(void *ctx_void) {
  struct uartdpi_ctx *ctx = (struct uartdpi_ctx *)ctx_void;

  return ctx->tmp_read;
}

void uartdpi_write(void *ctx_void, char c) {
  int rv;

  struct uartdpi_ctx *ctx = (struct uartdpi_ctx *)ctx_void;

  rv = write(ctx->host, &c, 1);
  assert(rv == 1 && "Write to pseudo-terminal failed.");

  if (ctx->log_file) {
    rv = fwrite(&c, sizeof(char), 1, ctx->log_file);
    assert(rv == 1 && "Write to log file failed.");
  }
}
