#include <iostream>
#include <thread>

#include "Local_Server/Crawler/Crawler.h"
#include "Local_Server/Data_Source/Data_Source.h"
#include "Local_Server/State_Report/State_Report.h"
#include "Local_Server/server/Global.h"

#include <SQLiteCpp/SQLiteCpp.h>
#include <SQLiteCpp/VariadicBind.h>
#include <codecvt>
#include <csignal>
#include <future>

#include "Local_Server/server/io_coro.h"
// ./server  ./config.json

#ifdef __linux__
#include <malloc.h>
#endif

struct Catch_Memory {
  Catch_Memory() {
    sm = (std::int64_t)get_system_memory();
    cur = (std::int64_t)get_process_memory();
  }
  std::int64_t MB = 1024 * 1024;
  bool catch_ok() {
    auto old_memory = cur;
    cur = (std::int64_t)get_process_memory();
    auto change_mb = (cur - old_memory) / MB;
    auto cur_mb = cur / MB;
    // std::cout << get_current_date_string() << " 时内存" << cur_mb << "MB  "
    // << "   变更" << change_mb << "MB" << std::endl;

    if (cur > memory_max) {
      auto rate = (double)cur / (double)sm;
      std::cout << get_current_date_string() + " 抓住内存暴涨:" << cur_mb
                << "MB" << "   变更" << change_mb << "MB" << std::endl;
      std::cout << "\t内存占用" << rate << "%" << std::endl;
      stop_program = SIGINT;

#if WIN32
#else
      system("top");
#endif
      return true;
    }
    return false;
  }
#if WIN32
  std::int64_t memory_max = 1 * 1024 * 1024 * 1024;
#else
  std::int64_t memory_max = 1 * 1024 * 1024 * 1024;
#endif
  std::int64_t cur;
  std::int64_t sm;
};





int psc_main(int argc, char *argv[]) {
  std::cout << "wyc_main" << std::endl;

  if (argc >= 2) {
    std::string config_path = argv[1];
    if (config_path.at(0) == '@') {
      config_path.replace(0, 1, get_exe_dir());
    }
    ::default_config_path = config_path;
  }

  // std::cout << get_stack_trace() << std::endl;

  init_signal_config({SIGINT, SIGTERM},
#ifdef WIN32
                     {}
#else
                     {SIGPIPE}
#endif
  );
  auto clear = []() {
    std::cout << "保存配置文件 " << LOG_POS << std::endl;
    Config::save();
    std::cout << "shutdown" << std::endl;

    auto i = Global::instance();
    i->svr.stop();
    i->thread_manager.stop_all_thread();

    Global::instance()->dsp_config.close_dsp_device();
    std::cout << "destroy开始" << std::endl;
    Global::destroy();
    std::cout << " Base_Logger_Manager::instance()->destroy()开始" << std::endl;
    Base_Logger_Manager::destroy();
    std::cout << " clear完成" << std::endl;
    std::cout << " 正常退出" << std::endl;
  };


  auto g = Global::instance();
  Psc::set_fail_fast([](const std::string& name) {
    // 如果是在 Global::instance()  里面失败是不能调用这个处理函数的
    auto g = Global::instance();
    std::cout << "set_fail_fast 退出原因： 222" << name << std::endl;
    std::cout << "shutdown" << LOG_POS << std::endl;


    auto id = std::this_thread::get_id();
    std::cout << "id: " << id << std::endl;



    Detach_Thread *dt = g->thread_manager.get_thread(id);
    if (!dt)
    {
      std::cout << VAR_STR_1((void*)dt) << std::endl;
      std::terminate();
    }


    std::set<std::string> excluded_thread;
    excluded_thread.insert(dt->name);
    std::cout <<  dt->name << std::endl;



    // std::cout << "保存配置文件 " << LOG_POS << std::endl;
    // Config::save();



    g->svr.stop();
    g->thread_manager.stop_all_thread(10000, excluded_thread);
    std::cout << "22222222" << std::endl;
    Global::instance()->dsp_config.close_dsp_device();

    std::cout << "destroy开始" << std::endl;
    Global::destroy();
    std::cout << " Base_Logger_Manager::instance()->destroy()开始" << std::endl;
    Base_Logger_Manager::destroy();
    std::cout << " clear完成" << std::endl;
    std::cout << " std::exit(75) " << name << std::endl;
    std::exit(75);
    std::cout << "std::exit(75) 完成：" << name << std::endl;
  });



  Detach_Thread_Manager &manager = g->thread_manager;
  std::cout << "[主线程:" << std::this_thread::get_id() << "]" << " \n"
            << std::flush;
  manager.test_and_start_thread(
      "web服务器线程", [g](std::atomic<bool> &running) {
        auto &c = Global::instance()->device_config;
        std::string ip = "0.0.0.0";
#ifdef WIN32
        ip = "127.0.0.1";
#endif
        Net_Config *device = c.list.get("device").value();
        std::cout << "http://" + ip + ":" + std::to_string(device->port) + "\n"
                  << std::flush;
        std::cout << "http://" + device->ip + ":" +
                         std::to_string(device->port) + "\n"
                  << std::flush;
        if (!g->svr.listen("0.0.0.0", device->port)) {
          if (running.load(std::memory_order_acquire)) {
            std::cout << "http://" + ip + ":" + std::to_string(device->port) +
                             "启动失败 退出！\n"
                      << std::flush;
            std::cout << "http://" + device->ip + ":" +
                             std::to_string(device->port) + "启动失败 退出！\n"
                      << std::flush;
            std::exit(0);
          }
        }
      });
  // manager.test_and_start_thread("io_coro 协程线程", io_coro);
  static int t = Global::instance()->mode_acs.read_milliseconds;

  g->dsp_config.init_env();

  bool enable = g->mlat.enable;

  Coro coro;

  coro.start();


  // Catch_Memory cm;
  while (stop_program == 0) {
    for (auto &ds : g->mode_acs.data_source_config.map.list()) {
      ds->delete_timeout_aircraft();
    }

    if (enable) {
      g->mlat.refresh();
    }
#ifdef __linux__
    if (g->mode_acs.monitor_msg_live)
      malloc_trim(0);
#endif
    std::this_thread::sleep_for(std::chrono::seconds(3));
    if (Global::instance()->init_ok) {
      // if (cm.catch_ok()) {
      //     stop_program = SIGINT;
      //     break;
      // }
    }
  }

  coro.stop();

  if (stop_program == SIGINT || stop_program == SIGTERM) {
    clear();
  }

  return 0;
}


int main(int argc, char* argv[]) {
    return redict_main_with_gtest(argc, argv, psc_main);
}




// int main(int argc, char* argv[]) {
//
//     Psc::set_console_utf8();
//     std::cout << "asio 起点" << std::endl;
//
//     return 0;
// }
