/**
 * @file aiagent_app.c
 * @brief JieLi application bridge for the AI Agent SDK
 */

#include "system/includes.h"
#include "os/os_api.h"
#include "action.h"
#include "event/key_event.h"
#include "event/device_event.h"
#include "event/net_event.h"
#include <stdbool.h>
#include "scene_ai_study.h"
#include "scene_ai_printer.h"
#include "aiagent_engine.h"
#include "aiagent_scene.h"
#include "scene_ai_toy.h"
#include "hal_log.h"
#include "net/config_network.h"

#define TAG "[AIAGENT_APP]"

extern void bt_connection_enable(void);
extern void bt_connection_disable(void);
extern void wifi_return_sta_mode(void);

static volatile bool s_network_ready = false;
static volatile bool s_engine_started = false;
static bool s_bt_enabled = false;

/* 双击进入 / 退出 WiFi 配网 */
static void aiagent_toggle_wifi_config(void)
{
    if (!is_in_config_network_state()) {
        BD_LOGI(TAG, "enter wifi config");
        if (!s_bt_enabled) {
            s_bt_enabled = true;
            bt_connection_enable();
        }
        config_network_start();
    } else {
        BD_LOGI(TAG, "exit wifi config");
        config_network_stop();
        wifi_return_sta_mode();
        if (s_bt_enabled) {
            s_bt_enabled = false;
            bt_connection_disable();
        }
    }
}

static void aiagent_on_network_event(struct net_event *event)
{
    switch (event->event) {
    case NET_EVENT_CONNECTED:
        BD_LOGI(TAG, "network connected");
        s_network_ready = true;
        aiagent_scene_notify_network(NET_EVENT_CONNECTED);

        if (!s_engine_started) {
            aiagent_engine_t engine = aiagent_scene_get_engine();
            if (engine) {
                BD_LOGI(TAG, "starting engine...");
                int ret = aiagent_engine_start(engine);
                if (ret == 0) {
                    s_engine_started = true;
                    BD_LOGI(TAG, "engine started OK");
                } else {
                    BD_LOGE(TAG, "engine start fail: %d", ret);
                }
            }
        }
        break;

    case NET_EVENT_DISCONNECTED:
        BD_LOGI(TAG, "network disconnected");
        s_network_ready = false;
        s_engine_started = false;
        aiagent_scene_notify_network(NET_EVENT_DISCONNECTED);

        {
            aiagent_engine_t engine = aiagent_scene_get_engine();
            if (engine) {
                aiagent_engine_stop(engine);
            }
        }
        break;

    case NET_EVENT_SMP_CFG_FINISH:
        BD_LOGI(TAG, "wifi config: got ssid, connecting");
        if (is_in_config_network_state()) {
            config_network_stop();
            config_network_connect();
        }
        break;

    default:
        break;
    }
}

static void aiagent_on_key_event(struct key_event *key)
{
    aiagent_engine_t engine = aiagent_scene_get_engine();

    aiagent_scene_notify_key(key->action, key->value);

    /* 双击进入 / 退出 WiFi 配网，不依赖引擎与网络 */
    if (key->action == KEY_EVENT_DOUBLE_CLICK && key->value == KEY_OK) {
        aiagent_toggle_wifi_config();
        return;
    }

    if (!engine || !s_engine_started) {
        return;
    }

    switch (key->action) {
    case KEY_EVENT_CLICK:
        if (key->value == KEY_OK || key->value == KEY_MODE) {
            aiagent_engine_notify_key_press(engine);
        }
        break;

    case KEY_EVENT_LONG:
        if (key->value == KEY_OK || key->value == KEY_MODE) {
            aiagent_engine_notify_key_long_press(engine);
        }
        break;

    case KEY_EVENT_HOLD:
        break;

    case KEY_EVENT_UP:
        if (key->value == KEY_OK || key->value == KEY_MODE) {
            aiagent_engine_notify_key_release(engine);
        }
        break;

    default:
        break;
    }
}

static int aiagent_event_handler(struct application *app, struct sys_event *event)
{
    switch (event->type) {
    case SYS_KEY_EVENT:
        aiagent_on_key_event((struct key_event *)event->payload);
        return true;

    case SYS_NET_EVENT:
        aiagent_on_network_event((struct net_event *)event->payload);
        return true;

    case SYS_DEVICE_EVENT:
        return false;

    case SYS_BT_EVENT:
        return false;

    default:
        return false;
    }
}

static int aiagent_state_machine(struct application *app, enum app_state state,
                                  struct intent *it)
{
    switch (state) {
    case APP_STA_CREATE:
        BD_LOGI(TAG, "APP_STA_CREATE");
        break;

    case APP_STA_START:
        BD_LOGI(TAG, "APP_STA_START");

        aiagent_scene_register(scene_ai_toy_get_ops());

        {
            int ret = aiagent_scene_start("ai_toy");
            if (ret != 0) {
                BD_LOGE(TAG, "scene start fail: %d", ret);
            } else {
                BD_LOGI(TAG, "scene 'ai_toy' ready, waiting for network...");
            }
        }
        break;

    case APP_STA_PAUSE:
        BD_LOGI(TAG, "APP_STA_PAUSE");
        break;

    case APP_STA_RESUME:
        BD_LOGI(TAG, "APP_STA_RESUME");
        break;

    case APP_STA_STOP:
        BD_LOGI(TAG, "APP_STA_STOP");
        aiagent_scene_stop();
        s_engine_started = false;
        s_network_ready = false;
        break;

    case APP_STA_DESTROY:
        BD_LOGI(TAG, "APP_STA_DESTROY");
        break;

    default:
        break;
    }

    return 0;
}

/* register "aiagent" application with the JieLi framework */
static const struct application_operation aiagent_ops = {
    .state_machine  = aiagent_state_machine,
    .event_handler  = aiagent_event_handler,
};

REGISTER_APPLICATION(aiagent_app) = {
    .name   = "aiagent",
    .action = ACTION_MUSIC_PLAY_MAIN,
    .ops    = &aiagent_ops,
    .state  = APP_STA_DESTROY,
};
