/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 "os/mynewt.h"
#include "hal/hal_uart.h"
#include "bsp/bsp.h"

#ifdef MN_LINUX
#include <pty.h>
#endif
#ifdef MN_OSX
#include <util.h>
#endif
#ifdef MN_FreeBSD
#include <libutil.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <errno.h>

#include "mcu/mcu_sim.h"
#include "native_uart_cfg_priv.h"

#define UART_CNT                2

#if MYNEWT_VAL(CONSOLE_UART_TX_BUF_SIZE)
#define UART_MAX_BYTES_PER_POLL	MYNEWT_VAL(CONSOLE_UART_TX_BUF_SIZE) - 2
#else
#define UART_MAX_BYTES_PER_POLL	64
#endif
#define UART_POLLER_STACK_SZ	OS_STACK_ALIGN(1024)

struct uart {
    int u_open;
    int u_fd;
    int u_tx_run;
    int u_rx_char;
    hal_uart_rx_char u_rx_func;
    hal_uart_tx_char u_tx_func;
    hal_uart_tx_done u_tx_done;
    void *u_func_arg;
};

const char *native_uart_dev_strs[UART_CNT];

/*
 * XXXX should try to use O_ASYNC/SIGIO for byte arrival notification,
 * so we wouldn't need an OS for pseudo ttys.
 */
char *native_uart_log_file = NULL;
static int uart_log_fd = -1;

static struct uart uarts[UART_CNT];
static int uart_poller_running;
static struct os_task uart_poller_task;
static os_stack_t uart_poller_stack[UART_POLLER_STACK_SZ];

static void
uart_open_log(void)
{
    if (native_uart_log_file && uart_log_fd < 0) {
        uart_log_fd = open(native_uart_log_file, O_WRONLY | O_CREAT | O_TRUNC,
          0666);
        assert(uart_log_fd >= 0);
    }
}

static void
uart_log_data(struct uart *u, int istx, uint8_t data)
{
    static struct {
        struct uart *uart;
        int istx;
        uint32_t time;
        int chars_in_line;
    } state = {
        .uart = NULL,
        .istx = 0
    };
    uint32_t now;
    char tmpbuf[32];
    int len;

    if (uart_log_fd < 0) {
        return;
    }
    now = os_time_get();
    if (state.uart) {
        if (u != state.uart || now != state.time || istx != state.istx) {
            /*
             * End current printout.
             */
            if (write(uart_log_fd, "\n", 1) != 1) {
                assert(0);
            }
            state.uart = NULL;
        } else {
            if (state.chars_in_line == 8) {
                if (write(uart_log_fd, "\n\t", 2) != 2) {
                    assert(0);
                }
                state.chars_in_line = 0;
            }
            len = snprintf(tmpbuf, sizeof(tmpbuf), "%c (%02x) ",
              isalnum(data) ? data : '?', data);
            if (write(uart_log_fd, tmpbuf, len) != len) {
                assert(0);
            }
            state.chars_in_line++;
        }
    }
    if (u && state.uart == NULL) {
        len = snprintf(tmpbuf, sizeof(tmpbuf), "%u:uart%d %s\n\t%c (%02x) ",
          now, u - uarts, istx ? "tx" : "rx", isalnum(data) ? data : '?', data);
        if (write(uart_log_fd, tmpbuf, len) != len) {
            assert(0);
        }
        state.chars_in_line = 1;
        state.uart = u;
        state.istx = istx;
        state.time = now;
    }
}

static int
uart_transmit_char(struct uart *uart)
{
    int sr;
    int rc;
    char ch;

    OS_ENTER_CRITICAL(sr);
    rc = uart->u_tx_func(uart->u_func_arg);
    if (rc < 0) {
        /*
         * No more data to send.
         */
        uart->u_tx_run = 0;
        if (uart->u_tx_done) {
            uart->u_tx_done(uart->u_func_arg);
        }
        OS_EXIT_CRITICAL(sr);
        return 0;
    }
    ch = rc;
    uart_log_data(uart, 1, ch);
    OS_EXIT_CRITICAL(sr);
    rc = write(uart->u_fd, &ch, 1);
    if (rc <= 0) {
        /* XXX EOF/error, what now? */
        return -1;
    }
    return 0;
}

static void
uart_poller(void *arg)
{
    int i;
    int rc;
    int bytes;
    int sr;
    int didwork;
    unsigned char ch;
    struct uart *uart;

    while (1) {
        for (i = 0; i < UART_CNT; i++) {
            if (!uarts[i].u_open) {
                continue;
            }
            uart = &uarts[i];

            for (bytes = 0; bytes < UART_MAX_BYTES_PER_POLL; bytes++) {
                didwork = 0;
                if (uart->u_tx_run) {
                    uart_transmit_char(uart);
                    didwork = 1;
                }
                if (uart->u_rx_char < 0) {
                    rc = read(uart->u_fd, &ch, 1);
                    if (rc == 0) {
                        /* XXX EOF, what now? */
                        assert(0);
                    } else if (rc > 0) {
                        uart->u_rx_char = ch;
                    }
                }
                if (uart->u_rx_char >= 0) {
                    OS_ENTER_CRITICAL(sr);
                    uart_log_data(uart, 0, uart->u_rx_char);
                    rc = uart->u_rx_func(uart->u_func_arg, uart->u_rx_char);
                    /* Delivered */
                    if (rc >= 0) {
                        uart->u_rx_char = -1;
                        didwork = 1;
                    }
                    OS_EXIT_CRITICAL(sr);
                }
                if (!didwork) {
                    break;
                }
            }
        }
        uart_log_data(NULL, 0, 0);
        os_time_delay(OS_TICKS_PER_SEC / 100);
    }
}

static void
set_nonblock(int fd)
{
    int flags;

    flags = fcntl(fd, F_GETFL);
    if (flags == -1) {
        const char msg[] = "fcntl(F_GETFL) fail";
        write(1, msg, sizeof(msg));
        return;
    }
    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
        const char msg[] = "fcntl(F_SETFL) fail";
        write(1, msg, sizeof(msg));
        return;
    }
}

static int
uart_pty_set_attr(int fd)
{
    struct termios tios;

    if (tcgetattr(fd, &tios)) {
        const char msg[] = "tcgetattr() failed";
        write(1, msg, sizeof(msg));
        return -1;
    }

    tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
    tios.c_cflag |= CS8 | CREAD;
    tios.c_iflag = IGNPAR;
    tios.c_oflag = 0;
    tios.c_lflag = 0;
    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
        const char msg[] = "tcsetattr() failed";
        write(1, msg, sizeof(msg));
        return -1;
    }
    return 0;
}

static int
uart_pty(int port)
{
    int fd;
    int loop_slave;
    char pty_name[32];
    char msg[64];

    if (openpty(&fd, &loop_slave, pty_name, NULL, NULL) < 0) {
        const char msg[] = "openpty() failed";
        write(1, msg, sizeof(msg));
        return -1;
    }

    if (uart_pty_set_attr(loop_slave)) {
        goto err;
    }

    snprintf(msg, sizeof(msg), "uart%d at %s\n", port, pty_name);
    write(1, msg, strlen(msg));
    return fd;
err:
    close(fd);
    close(loop_slave);
    return -1;
}

/**
 * Opens an external device terminal (/dev/cu.<...>).
 */
static int
uart_open_dev(int port, int32_t baudrate, uint8_t databits,
              uint8_t stopbits, enum hal_uart_parity parity,
              enum hal_uart_flow_ctl flow_ctl)
{
    const char *filename;
    int fd;
    int rc;

    filename = native_uart_dev_strs[port];
    assert(filename != NULL);

    fd = open(filename, O_RDWR);
    if (fd < 0) {
        return -1;
    }

    rc = uart_dev_set_attr(fd, baudrate, databits,
                           stopbits, parity, flow_ctl);
    if (rc != 0) {
        close(fd);
        return rc;
    }

    dprintf(1, "uart%d at %s\n", port, filename);

    return fd;
}

void
hal_uart_start_tx(int port)
{
    int sr;

    if (port >= UART_CNT || uarts[port].u_open == 0) {
        return;
    }
    OS_ENTER_CRITICAL(sr);
    uarts[port].u_tx_run = 1;
    if (!os_started()) {
        /*
         * XXX this is a hack.
         */
        uart_transmit_char(&uarts[port]);
    }
    OS_EXIT_CRITICAL(sr);
}

void
hal_uart_start_rx(int port)
{
    /* nothing to do here */
}

void
hal_uart_blocking_tx(int port, uint8_t data)
{
    if (port >= UART_CNT || uarts[port].u_open == 0) {
        return;
    }

    /* XXX: Count statistics and add error checking here. */
    (void) write(uarts[port].u_fd, &data, sizeof(data));
}

int
hal_uart_init_cbs(int port, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done,
  hal_uart_rx_char rx_func, void *arg)
{
    struct uart *uart;
    int rc;

    if (port >= UART_CNT) {
        return -1;
    }

    uart = &uarts[port];
    if (uart->u_open) {
        return -1;
    }
    uart->u_tx_func = tx_func;
    uart->u_tx_done = tx_done;
    uart->u_rx_func = rx_func;
    uart->u_func_arg = arg;
    uart->u_rx_char = -1;

    if (!uart_poller_running) {
        uart_poller_running = 1;
        rc = os_task_init(&uart_poller_task, "uartpoll", uart_poller, NULL,
          MYNEWT_VAL(MCU_UART_POLLER_PRIO), OS_WAIT_FOREVER, uart_poller_stack,
          UART_POLLER_STACK_SZ);
        assert(rc == 0);
    }
    return 0;
}

int
hal_uart_config(int port, int32_t baudrate, uint8_t databits, uint8_t stopbits,
  enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
{
    struct uart *uart;

    if (port >= UART_CNT) {
        return -1;
    }

    uart = &uarts[port];
    if (uart->u_open) {
        return -1;
    }

    if (native_uart_dev_strs[port] == NULL) {
        uart->u_fd = uart_pty(port);
    } else {
        uart->u_fd = uart_open_dev(port, baudrate, databits, stopbits,
                                   parity, flow_ctl);
    }

    if (uart->u_fd < 0) {
        return -1;
    }
    set_nonblock(uart->u_fd);


    uart_open_log();
    uart->u_open = 1;
    return 0;
}

int
hal_uart_close(int port)
{
    struct uart *uart;
    int rc;

    if (port >= UART_CNT) {
        rc = -1;
        goto err;
    }

    uart = &uarts[port];
    if (!uart->u_open) {
        rc = -1;
        goto err;
    }

    close(uart->u_fd);

    uart->u_open = 0;
    return (0);
err:
    return (rc);
}

int
hal_uart_init(int port, void *arg)
{
    return (0);
}

int
uart_set_dev(int port, const char *dev_str)
{
    if (port < 0 || port >= UART_CNT) {
        return SYS_EINVAL;
    }

    if (uarts[port].u_open) {
        return SYS_EBUSY;
    }

    native_uart_dev_strs[port] = dev_str;

    return 0;
}
