#ifndef ASYNC_CLIENT_H
#define ASYNC_CLIENT_H
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <chrono>
#include <mutex>
#include <thread>
#include <atomic>
#include <string>
#include <unistd.h>
#include "glog/logging.h"

// using namespace std ;
// using boost::asio::ip::udp;
// using boost::asio::ip::tcp;
// using namespace boost::asio;
#define MAX_LENGTH 50000
#define READ_TIMEOUT_MILLISECONDS 5000
typedef void (*fundata_t)(const char *data, const int len, const void *p);

/**
 * 异步tcp通信客户端
 * */
class Async_Client
{
public:
  // 有参构造
  Async_Client(boost::asio::io_service &io_service, boost::asio::ip::tcp::endpoint endpoint, fundata_t fundata_, void *p);
  // 析构
  ~Async_Client();
  // 连接状态返回
  bool client_connection_status();
  // 初始化状态返回
  bool client_initialize_status();
  // 初始化
  bool initialize(bool with_reconnection = true);
  // 关闭
  bool close();

private:
  // 连接检查线程函数
  static void connection_check(Async_Client *p);
  // 连接
  void socket_connect();
  // 关闭连接
  void socket_close();
  // 重新设置连接
  void socket_reconnect();
  // 异步写入
  void client_async_write(char *buf, int len);
  // 异步读取
  void client_async_read();
  // 异步读回调
  void handle_read(const boost::system::error_code &error,
                   size_t bytes_transferred);
  // 异步写回调
  void handle_write(const boost::system::error_code &error);
  // 异步连接回调
  void handle_connect(const boost::system::error_code &error);

  boost::asio::io_service &iosev;      // 异步控制服务
  boost::asio::ip::tcp::socket socket; // socket句柄
  boost::asio::ip::tcp::endpoint m_ep; // 连接参数

  char m_origin_data_[MAX_LENGTH]; // 原始数据
  // std::mutex  m_data_mutex;               // 原始数据访问锁, 顺序执行，无需加锁
  std::atomic<bool> mb_with_reconnection; // 开启自动重连
  std::atomic<bool> mb_connected;         // 连接状态
  std::atomic<bool> mb_initialized;       // 初始化是否成功

  fundata_t m_fundata; // 数据处理回调
  void *mp_handle;     // 外部句柄

  std::chrono::steady_clock::time_point m_last_read_time; //最后一次读取时间
  std::thread *m_connection_check_thread;                 // 连接状态主动检查线程
public:
  std::atomic<bool> mb_exit; // 系统是否需要关闭
};

#endif // ASYNC_CLIENT_H
