
#define DYNAMIC_LOAD
#include "ethercat.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void on_log(int category, const char* msg)
{
    if (category <= 2) {
        printf("[LOG] %s\n", msg);
    }
}

static void on_state_change(uint16_t master, uint16_t slave, int old_s, int new_s)
{
    const char* names[] = {"NONE","INIT","PRE_OP","BOOT","SAFE_OP","?","?","?","OP"};
    const char* old_name = (old_s >= 0 && old_s <= 8) ? names[old_s] : "?";
    const char* new_name = (new_s >= 0 && new_s <= 8) ? names[new_s] : "?";
    printf("从站 %d 状态变化: %s -> %s\n", slave, old_name, new_name);
}

static char* read_file(const char* path)
{
    FILE* f;
    long len;
    char* buf;

    f = fopen(path, "rb");
    if (!f) return NULL;

    fseek(f, 0, SEEK_END);
    len = ftell(f);
    fseek(f, 0, SEEK_SET);

    buf = (char*)malloc(len + 1);
    if (!buf) { fclose(f); return NULL; }

    fread(buf, 1, len, f);
    buf[len] = '\0';
    fclose(f);
    return buf;
}

int main(int argc, char* argv[])
{
    dll_t dll;
    uint16_t master;
    char method = 0;

    printf("=== DarraEtherCAT C SDK 高级示例 (EcInit) ===\n\n");

    if (!LOAD_DLL(&dll, "Darra.Core.dll")) {
        printf("错误: 无法加载 Darra.Core.dll\n");
        return 1;
    }

    if (dll.SetLogCallback) dll.SetLogCallback(on_log);

    if (dll.RegisterStateChangeSync) {
        dll.RegisterStateChangeSync(on_state_change);
    }

    if (argc >= 2 && strcmp(argv[1], "--json") == 0 && argc >= 3) {
        char* json = read_file(argv[2]);
        if (!json) {
            printf("错误: 无法读取配置文件 %s\n", argv[2]);
            UNLOAD_DLL(&dll);
            return 1;
        }

        printf("正在通过 JSON 配置初始化...\n");
        master = dll.EcInit(json);
        free(json);

        if (master == 0) {
            printf("错误: EcInit 失败\n");
            UNLOAD_DLL(&dll);
            return 1;
        }
        printf("EcInit 成功, 主站索引: %d\n", master);
        method = 'A';
    }

    else if (argc >= 2 && strcmp(argv[1], "--file") == 0 && argc >= 3) {
        printf("正在从文件初始化: %s\n", argv[2]);
        master = dll.EcInitFromFile(argv[2]);

        if (master == 0) {
            printf("错误: EcInitFromFile 失败\n");
            UNLOAD_DLL(&dll);
            return 1;
        }
        printf("EcInitFromFile 成功, 主站索引: %d\n", master);
        method = 'B';
    }

    else if (argc >= 3) {
        const char* adapter = argv[1];
        const char* secondary = (argc >= 4) ? argv[2] : "";
        const char* config_file = (argc >= 4) ? argv[3] : argv[2];

        master = dll.Initialize();
        if (master == 0) {
            printf("错误: Initialize 失败\n");
            UNLOAD_DLL(&dll);
            return 1;
        }

        uint16_t slave_count = dll.SetNetwork(master, adapter, secondary);
        if (slave_count == 0 || slave_count == 0xFFFF) {
            printf("错误: SetNetwork 失败\n");
            dll.Dispose(master);
            UNLOAD_DLL(&dll);
            return 1;
        }
        printf("发现 %d 个从站\n", slave_count);

        if (config_file) {
            char* json = read_file(config_file);
            if (json) {
                int loaded = dll.LoadConfigJson(master, json);
                printf("加载配置: %d 个参数\n", loaded);
                free(json);
            }
        }

        if (dll.AutoConfigureSM) {
            int sm_count = dll.AutoConfigureSM(master, 0);
            printf("自动配置 SM: %d 个从站\n", sm_count);
        }

        if (!dll.SetStateSequence(master, EC_STATE_OPERATIONAL, 15000)) {
            printf("错误: SetStateSequence 失败\n");
            dll.Dispose(master);
            UNLOAD_DLL(&dll);
            return 1;
        }

        dll.Start(master);
        printf("已进入 OP 状态并启动 PDO 循环\n");
        method = 'C';
    }
    else {
        printf("用法:\n");
        printf("  %s --json <config.json>              从 JSON 字符串初始化\n", argv[0]);
        printf("  %s --file <config.json>              从 JSON 文件路径初始化\n", argv[0]);
        printf("  %s <adapter> [config.json]           分步初始化\n", argv[0]);
        printf("  %s <primary> <secondary> [config.json] 冗余模式\n", argv[0]);
        UNLOAD_DLL(&dll);
        return 0;
    }

    printf("\n运行中, 按 Enter 键停止...\n\n");

    {
        int32_t out_size, in_size;
        uint8_t* out_ptr;
        uint8_t* in_ptr;

        for (uint16_t s = 1; s <= 16; s++) {
            out_size = in_size = 0;
            out_ptr = in_ptr = NULL;

            if (dll.GetIO(master, s, &out_size, &out_ptr, &in_size, &in_ptr) == 0) {
                if (out_size > 0 || in_size > 0) {
                    printf("  从站 %d: 输出 %d 字节 @ %p, 输入 %d 字节 @ %p\n",
                           s, out_size, (void*)out_ptr, in_size, (void*)in_ptr);
                }
            } else {
                break;
            }
        }
    }

    getchar();

    printf("正在关闭...\n");
    if (method == 'A' || method == 'B') {

        dll.EcClose(master);
    } else {

        dll.Stop(master);
        dll.Dispose(master);
    }
    UNLOAD_DLL(&dll);
    printf("已退出\n");

    return 0;
}
