#include "ltr/include/ltrk415api.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#ifdef _WIN32
    #include <locale.h>
#endif

#define ERR_INVALID_USAGE           -1
#define ERR_MODULE_NOT_FOUND        -2

static int f_get_slot(e_LTR01_SUBID req_subid, int *slot, char* serial) {
    TLTR srv;
    int fnd=0;
    INT err = LTR_OK;
    LTR_Init(&srv);
    err=LTR_OpenSvcControl(&srv, LTRD_ADDR_DEFAULT, LTRD_PORT_DEFAULT);
    if (err != LTR_OK) {
        fprintf(stderr, "Не удалось установить связь с LTR-сервером. Ошибка %d: %s!\n",
                err, LTR_GetErrorString(err));
    } else {
        char serial_list[LTR_CRATES_MAX][LTR_CRATE_SERIAL_SIZE];
        err=LTR_GetCrates(&srv, (BYTE*)&serial_list[0][0]);
        LTR_Close(&srv);
        if (err != LTR_OK) {
            fprintf(stderr, "Не удалось получить список крейтов. Ошибка %d: %s!\n",
                    err, LTR_GetErrorString(err));
        } else {
            int crate_ind;
            for (crate_ind = 0 ; (crate_ind < LTR_CRATES_MAX) && !fnd; crate_ind++) {
                if (serial_list[crate_ind][0] != '\0') {
                    TLTR crate;
                    INT crate_err = LTR_OK;
                    LTR_Init(&crate);
                    crate_err = LTR_OpenCrate(&crate, LTRD_ADDR_DEFAULT, LTRD_PORT_DEFAULT,
                                               LTR_CRATE_IFACE_UNKNOWN, serial_list[crate_ind]);
                    if (crate_err == LTR_OK) {
                        WORD mids[LTR_MODULES_PER_CRATE_MAX];
                        crate_err = LTR_GetCrateModules(&crate, mids);
                        if (crate_err == LTR_OK) {
                            int module_ind;
                            for (module_ind = 0; (module_ind < LTR_MODULES_PER_CRATE_MAX) && !fnd; module_ind++) {
                                if (mids[module_ind]==LTR_MID_LTR01) {
                                    WORD subid;
                                    crate_err = LTR01_GetSubID(LTRD_ADDR_DEFAULT, LTRD_PORT_DEFAULT,
                                                               crate.csn, LTR_CC_CHNUM_MODULE1+module_ind,
                                                               &subid, NULL);
                                    if ((crate_err == LTR_OK) && (subid == req_subid)) {
                                        fnd = 1;
                                        strcpy(serial, crate.csn);
                                        *slot = module_ind + LTR_CC_CHNUM_MODULE1;
                                    }
                                }
                            }
                        }
                        LTR_Close(&crate);
                    }
                }
            }
        }
    }

    if (err == LTR_OK) {
        if (!fnd) {
            fprintf(stderr, "Ни одного модуля не было найдено!\n");
            err = ERR_MODULE_NOT_FOUND;
        } else {
            printf("Найден модуль: крейт %s, слот %d\n", serial, *slot);
        }
    }
    return err;
}


static const BYTE states[] = {
    LTRK415_OUT_SW_STATE_ON,
    LTRK415_OUT_SW_STATE_OFF,
    LTRK415_OUT_SW_STATE_ON,
    LTRK415_OUT_SW_STATE_OFF,
    LTRK415_OUT_SW_STATE_ON_INV,
    LTRK415_OUT_SW_STATE_OFF,
    LTRK415_OUT_SW_STATE_ON_INV,
    LTRK415_OUT_SW_STATE_ON,
    LTRK415_OUT_SW_STATE_OFF,
    LTRK415_OUT_SW_STATE_ON
};


static WORD f_out_buf[512];



int main(int argc, char** argv) {
    INT err = LTR_OK, out=0;
    TLTRK415 hltrk415;

    char csn[LTR_CRATE_SERIAL_SIZE];
    int slot=LTR_CC_CHNUM_MODULE1;

#ifdef _WIN32
    /* для вывода русских букв в консоле... */
    setlocale(LC_ALL, "");
#endif
    /* находим нужный модуль */
    if (!err && !out) {
        err = f_get_slot(LTR01_SUBID_LTRK415, &slot, csn);
    }

    if (!err && !out) {
        LTRK415_Init(&hltrk415);
        /* устанавливаем соединение с модулем */
        err = LTRK415_Open(&hltrk415, LTRD_ADDR_DEFAULT, LTRD_PORT_DEFAULT, csn, slot);

        if (err != LTR_OK) {
            fprintf(stderr, "Не удалось установить связь с модулем. Ошибка %d (%s)\n",
                    err, LTRK415_GetErrorString(err));
        }

        if (LTRK415_IsOpened(&hltrk415) == LTR_OK) {
            /* после открытия модуля доступна информация, кроме версии прошивки ПЛИС */
            printf("Модуль открыт успешно!\n");
            printf("  Название модуля    = %s\n", hltrk415.ModuleInfo.Name);
            printf("  Серийный номер     = %s\n", hltrk415.ModuleInfo.Serial);
            printf("  Версия PLD         = %d\n", hltrk415.ModuleInfo.VerPLD);


            for (int i = 0; i < 512; ++i) {
                f_out_buf[i] = 0x200 + i;
            }


            err = LTRK415_SetOutChSwStates(&hltrk415, 0, states);
            if (err == LTR_OK) {
                err = LTRK415_LoadOutBuf(&hltrk415, 0, f_out_buf, sizeof(f_out_buf)/sizeof(f_out_buf[0]));
            }
            if (err == LTR_OK) {
                hltrk415.Cfg.Out.Ch[0].Source = LTRK415_CH_SRC_CBUF;
                hltrk415.Cfg.Out.Ch[0].InvertedData = TRUE;
                hltrk415.Cfg.Out.Ch[0].ActiveWithoutReq = FALSE;
                hltrk415.Cfg.Out.Ch[1].Source = LTRK415_CH_SRC_DIRECT;
                err = LTRK415_Configure(&hltrk415);
            }

            if (err == LTR_OK) {
                for (int i = 0; i < 512; ++i) {
                    f_out_buf[i] = 0x1FF - i;
                }
                err = LTRK415_LoadOutBuf(&hltrk415, 0, f_out_buf, sizeof(f_out_buf)/sizeof(f_out_buf[0]));
            }

            if (err == LTR_OK) {
                DWORD wrds[1024];
                TLTRK415_ACQ_DATA data[1024];

                err = LTRK415_StartAcq(&hltrk415, 0x1);
                //if (err == LTR_OK) {
                    int recv_res = LTRK415_Recv(&hltrk415, wrds, NULL, sizeof(wrds)/sizeof(wrds[9]), 1000);
                    if (recv_res > 0) {
                        err = LTRK415_ProcessData(&hltrk415, wrds, data, recv_res);
                    }

                err = LTRK415_StopAcq(&hltrk415);


                printf("%d", err);

                //}


            }

        }

        LTRK415_Close(&hltrk415);
    }

    return err;
}
