/**
 * Name: lua_script_basic.c
 * Desc: Loads a LUA script on a T7
**/

#ifdef _WIN32
    #include <winsock2.h>
    #include <ws2tcpip.h>
#else
    #include <arpa/inet.h>  // For inet_ntoa()
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "LabJackM.h"

#include "../LJM_Utilities.h"

void LoadLuaScript(int handle, const char * luaScript);

void ReadLuaInfo(int handle);

int main()
{
    int err = 0;
    int handle;

    // To place lua scripts directly in a c-string:
    //   http://stackoverflow.com/questions/1135841/c-multiline-string-literal
    // Note that the new lines have to be manually inserted using \n
    const char * luaScript =
        "LJ.IntervalConfig(0, 1000)\n"
        "  while true do\n"
        "  if LJ.CheckInterval(0) then\n"
        "    print(LJ.Tick())\n"
        "  end\n"
        "end\n";

    EnableLoggingLevel(LJM_TRACE);

    handle = OpenOrDie(LJM_dtT7, LJM_ctANY, "192.168.1.160");

    PrintDeviceInfoFromHandle(handle);
    GetAndPrint(handle, "FIRMWARE_VERSION");
    printf("\n");

    LoadLuaScript(handle, luaScript);

    GetAndPrint(handle, "LUA_RUN");
    GetAndPrint(handle, "LUA_DEBUG_NUM_BYTES");

    ReadLuaInfo(handle);

    err = LJM_Close(handle);
    ErrorCheck(err, "LJM_Close");

    WaitForUserIfWindows();

    return LJME_NOERROR;
}

void LoadLuaScript(int handle, const char * luaScript)
{
    const unsigned scriptLength = strlen(luaScript);

    const char * LUA_SOURCE_WRITE = "LUA_SOURCE_WRITE";

    double * aValues = malloc(sizeof(double) * scriptLength);
    int ErrorAddress = INITIAL_ERR_ADDRESS;

    unsigned valueI = 0;
    int err = 0;

    printf("Script length: %u\n", scriptLength);
    for (valueI = 0; valueI < scriptLength; valueI++) {
        aValues[valueI] = luaScript[valueI];
    }

    // As of T7 FIRMWARE_VERSION 1.0126, LUA_RUN must be written to twice
    // to disable a currently running script.
    WriteNameOrDie(handle, "LUA_RUN", 0);
    WriteNameOrDie(handle, "LUA_RUN", 0);
    WriteNameOrDie(handle, "LUA_SOURCE_SIZE", scriptLength);
    err = LJM_eWriteNameArray(handle, LUA_SOURCE_WRITE, scriptLength, aValues,
        &ErrorAddress);
    ErrorCheckWithAddress(err, ErrorAddress,
        "LJM_eWriteNameArray(%d, %s, %d, ...", handle, LUA_SOURCE_WRITE,
        scriptLength);
    WriteNameOrDie(handle, "LUA_DEBUG_ENABLE", 1);
    WriteNameOrDie(handle, "LUA_DEBUG_ENABLE_DEFAULT", 1);
    WriteNameOrDie(handle, "LUA_RUN", 1);

    free(aValues);
}

void ReadLuaInfo(int handle)
{
    int i;
    for (i = 0; i < 1000; i++) {
        MillisecondSleep(100);
        GetAndPrint(handle, "LUA_RUN");
        GetAndPrint(handle, "LUA_DEBUG_NUM_BYTES");
    }
}
