/*
 * Copyright (c) 2016-2022  Martin Lund
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "options.h"
#include "error.h"
#include "misc.h"
#include <lxi.h>

#define RESPONSE_LENGTH_MAX 0x500000
#define ID_LENGTH_MAX 65536

int scpi(char *ip, int port, int timeout, lxi_protocol_t protocol, char *command)
{
    char* response = malloc(RESPONSE_LENGTH_MAX);
    char command_buffer[1000];
    int device, length;;

    strip_trailing_space(command);

    if (protocol == RAW)
    {
        // Add newline to command string
        strcpy(command_buffer, command);
        command_buffer[strlen(command)] = '\n';
        command_buffer[strlen(command)+1] = 0;
        command = command_buffer;
    }

    // Connect
    device = lxi_connect(ip, port, NULL, timeout, protocol);
    if (device != LXI_OK)
    {
        error_printf("Unable to connect to LXI device\n");
        goto error_connect;
    }

    // Send SCPI command
    length = lxi_send(device, command, strlen(command), timeout);
    if (length < 0)
    {
        error_printf("Failed to send message\n");
        goto error_send;
    }

    // Only expect response in case we are firing a question command
    if (question(command))
    {
        length = lxi_receive(device, response, RESPONSE_LENGTH_MAX, timeout);
        if (length < 0)
        {
            error_printf("Failed to receive message\n");
            goto error_receive;
        }

        // Print response
        if (option.hex)
            hex_print(response, length);
        else
            {
                int i;
                for (i=0; i<length; i++)
                    putchar(response[i]);

                // Append newline if printing to tty terminal (not file)
                if ( isatty(fileno(stdout)) && (response[length-1] != '\n'))
                    printf("\n");
            }
    }

    // Disconnect
    lxi_disconnect(device);
    free(response);
    return 0;

error_send:
error_receive:

    // Disconnect
    lxi_disconnect(device);

error_connect:
    free(response);
    return 1;
}

int enter_interactive_mode(char *ip, int port, int timeout, lxi_protocol_t protocol)
{
    char* response = malloc(RESPONSE_LENGTH_MAX);
    int device, length;
    char *input = "";

    // Connect
    device = lxi_connect(ip, port, NULL, timeout, protocol);
    if (device != LXI_OK)
    {
        error_printf("Unable to connect to LXI device\n");
        goto error_connect;
    }

    printf("Connected to %s\n", ip);
    printf("Entering interactive mode (ctrl-d to quit)\n\n");

    // Enter line/command processing loop
    while (true)
    {
        input = readline("lxi> ");
        if (input == NULL)
            break;

        add_history(input);

        strip_trailing_space(input);

        // Skip empty lines
        if (strlen(input) == 0)
            continue;

        // Send entered input as SCPI command
        length = lxi_send(device, input, strlen(input), timeout);
        if (length < 0)
            error_printf("Failed to send message\n");

        // Only expect response in case we are firing a question command
        if (question(input))
        {
            length = lxi_receive(device, response, RESPONSE_LENGTH_MAX, timeout);
            if (length < 0)
            {
                error_printf("Failed to receive message\n");
            } else
            {
                // Make sure we terminate response string
                response[length] = 0;

                // Print response
                printf("%s", response);
            }
        }
    }

    printf("\n");

    // Disconnect
    lxi_disconnect(device);
    free(response);

    return 0;

error_connect:
    free(response);
    return 1;
}
