#include "main.h"
#include <unistd.h>

typedef int (*AppInitFn)(void);

typedef enum {
   APP_INIT_CORE = 0,
   APP_INIT_PLATFORM_DRIVER,
   APP_INIT_APP,
   APP_INIT_DEVICE_DRIVER,
   APP_INIT_MODULE_SERVICE,
   APP_INIT_RUNTIME,
} AppInitStage;

typedef struct {
   AppInitStage stage;
   const char *name;
   AppInitFn init;
   int fatal;
   int error_code;
   const char *fail_msg;
} AppInitStep;

static const char *app_init_stage_name(AppInitStage stage)
{
   switch (stage)
   {
   case APP_INIT_CORE:
      return "core";
   case APP_INIT_PLATFORM_DRIVER:
      return "platform_driver";
   case APP_INIT_APP:
      return "app";
   case APP_INIT_DEVICE_DRIVER:
      return "device_driver";
   case APP_INIT_MODULE_SERVICE:
      return "module_service";
   case APP_INIT_RUNTIME:
      return "runtime";
   default:
      return "unknown";
   }
}

static int init_wiringpi(void)
{
   return wiringPiSetup() == -1 ? -1 : 0;
}

static int init_audio_runtime(void)
{
   if (audio_init() == 0)
   {
      my_zlog_info("音频命令执行初始化成功");
   }
   return 0;
}

static int init_wifi_autoconfig(void)
{
   check_and_autoconfig_wifi();
   return 0;
}

static int init_go_deploy(void)
{
   return go_deploy_check_and_update();
}

static int init_ipc_unix_server(void)
{
   return ipc_start_unix_server(NULL);
}

static int init_wifi_config_agent(void)
{
   return wifi_config_agent_start();
}

static int init_worker_threads(void)
{
   return thread_start_init(thread_exit_time, thread_mqtt_beat,
                            thread_open_browser, thread_mqtt_reconnect,
                            thread_time_calculation, thread_play_mp3,
                            thread_steering_control);
}

static const AppInitStep s_init_steps[] = {
   {APP_INIT_CORE, "log", mylog_init, 1, -1, "日志初始化失败，错误代码"},

   {APP_INIT_PLATFORM_DRIVER, "wiringpi", init_wiringpi, 1, -2, "WiringPi setup failed!"},
   {APP_INIT_PLATFORM_DRIVER, "audio_config", audio_config_init, 0, 0, "音频配置初始化失败"},
   {APP_INIT_PLATFORM_DRIVER, "audio", init_audio_runtime, 0, 0, "音频初始化失败"},

   {APP_INIT_APP, "device_id", device_id_file_init, 1, -3, "设备id读取失败"},
   {APP_INIT_APP, "device_topic", device_mqtt_topic_init, 1, -4, "设备id判断失败"},
   {APP_INIT_APP, "wifi_autoconfig", init_wifi_autoconfig, 1, -5, "网络配网失败"},

   {APP_INIT_DEVICE_DRIVER, "hardware_iic", hardware_iic_init, 1, -7, "硬件iic初始化失败"},
   {APP_INIT_DEVICE_DRIVER, "shot_cooling", device_shot_cooling_init, 0, 0, "该设备没有冷却"},

   {APP_INIT_MODULE_SERVICE, "runtime_deps", runtime_deps_ensure, 0, 0, "运行时依赖检查/安装失败"},
   {APP_INIT_MODULE_SERVICE, "request_data", request_date, 1, -5, "请求数据失败"},
   {APP_INIT_MODULE_SERVICE, "mqtt_video", http_mqtt_video_init, 1, -6, "请求mqtt服务器和video数据失败"},
   {APP_INIT_MODULE_SERVICE, "go_deploy", init_go_deploy, 0, 0, "Go 程序检查/部署失败"},
   {APP_INIT_MODULE_SERVICE, "ipc_unix_server", init_ipc_unix_server, 1, -8, "IPC Unix Socket Server 启动失败"},
   {APP_INIT_MODULE_SERVICE, "wifi_config_agent", init_wifi_config_agent, 0, 0, "WiFi配置助手UDP服务启动失败"},

   {APP_INIT_RUNTIME, "worker_threads", init_worker_threads, 1, -7, "多线程初始化失败"},
};

static int run_init_steps(void)
{
   size_t count = sizeof(s_init_steps) / sizeof(s_init_steps[0]);
   AppInitStage last_stage = APP_INIT_CORE;

   for (size_t i = 0; i < count; i++)
   {
      const AppInitStep *step = &s_init_steps[i];
      if (i > 0 && step->stage != last_stage)
      {
         my_zlog_info("app init stage: %s", app_init_stage_name(step->stage));
      }
      last_stage = step->stage;

      int rc = step->init();
      if (rc == 0)
      {
         continue;
      }

      if (step->fatal)
      {
         my_zlog_error("%s", step->fail_msg);
         return step->error_code;
      }

      my_zlog_warn("%s", step->fail_msg);
   }

   return 0;
}

static void app_shutdown(void)
{
   wifi_config_agent_stop();
   thread_end_close();
   device_end_close(g_device_type);
   self_control_thread_close(); // 销毁自控的线程
   hardware_iic_close();
   my_zlog_info("程序关闭成功");
   my_log_close();              // 关闭日志
}

int main()
{
   int rc = run_init_steps();
   if (rc != 0)
   {
      return rc;
   }

   // 初始化全部完成，播放“连接成功”提示音，作为系统就绪的标志
   play_audio_file("connectionSuccessful.mp3");

   /* 工作线程在后台常驻；主线程不得 app_shutdown，否则 join 后进程退出被 systemd 拉起 */
   for (;;)
      sleep(3600);

   return 0;
}