#include "cmt_server.hpp"
#include <iostream>
#include <cstdio>
#include <cstring>
#include <memory>
#include <array>
#include <zlog.h>

#include "localserver/local_server.hpp"

extern zlog_category_t *zct;

void CMTSession::start() {
	data_ = (char*)malloc(CMT_TCP_LEN);
    memset(data_, 0, CMT_TCP_LEN);
    sessionSet_.insert(shared_from_this()); // 将会话添加到会话集合中
    do_read();
}
void CMTSession::set_data(char *data, int len) {
    memcpy(data_, data, len);
}
void CMTSession::do_write(std::size_t length) {
    auto self(shared_from_this());
    zlog_debug(zct, "[CMT] response len = %d", length);
    boost::asio::async_write(socket_, boost::asio::buffer(data_, length), [this, self](boost::system::error_code ec, std::size_t /*length*/) {
        if (ec) {
            zlog_error(zct, "[CMT] fail to send data, %s, %d", ec.category().name(), ec.value());
            socket_.close();
            sessionSet_.erase(shared_from_this());
        } else {
            zlog_debug(zct, "[CMT] waiting for next message...");
            do_read();
            // socket_.close();
            // sessionSet_.erase(shared_from_this());
        }
    });
}

void CMTServer::do_accept() {
    acceptor_.async_accept(socket_, [this](boost::system::error_code ec) {
        zlog_debug(zct, "[CMT] accept a socket");
        if (!ec) {
            std::make_shared<CMTSession>(std::move(socket_), sessionSet_)->start();
        }

        do_accept();
    });
}
void CMTSession::do_read() {
    auto self(shared_from_this());
    socket_.async_read_some(boost::asio::buffer(data_, CMT_TCP_LEN), [this, self](boost::system::error_code ec, std::size_t length) {
        if (!ec) { 
            if (length == 0) {
                zlog_warn(zct, "[CMT] Client disconnected (length 0)");
                sessionSet_.erase(shared_from_this());
                return;
            }
            
            if (length < 6 || data_[0] != 0xAA || data_[1] != 0x55 || data_[2] != 0xAA) {
                zlog_warn(zct, "[CMT] invalid data package, len:%d", length);
                do_read();
            }
            uint8_t cmd = data_[3];
            int payload_len = 0;
            memcpy((char*)&payload_len, (char*)&data_[4], 4);
            payload_len = htonl(payload_len);
            zlog_debug(zct, "[CMT] cmd: %d, message len: %d, payload len: %d, head:%2x-%2x-%2x", cmd, length, payload_len, data_[0], data_[1], data_[2]);
            zlog_debug(zct, "[CMT] payload bytes %d, %d", data_[4], data_[5]);
            int send_data_len = 0;
            char send_data[96100] = {0};
            LocalServer::HandleTcp_cmd(data_,send_data,cmd,send_data_len,payload_len);
            PackageHead pkg_head;
            pkg_head.head[0] = 0xAA;
            pkg_head.head[1] = 0x55;
            pkg_head.head[2] = 0xAA;
            pkg_head.cmd = cmd;
            pkg_head.len = send_data_len;
            memset(data_,0,CMT_TCP_LEN);
            memcpy(data_, &pkg_head, head_len_);
            memcpy(data_ + head_len_, &send_data, send_data_len);   
            do_write(head_len_ + send_data_len);
                        
        } else if (ec == boost::asio::error::eof){
            zlog_warn(zct, "[CMT] Client disconnect the connection");            
            sessionSet_.erase(shared_from_this());
        } else if (ec == boost::asio::error::connection_reset){
            zlog_warn(zct, "[CMT] Connection reset by client");            
            sessionSet_.erase(shared_from_this());
        } else {
            zlog_error(zct, "[CMT] Error message, reason: %s", ec.message().c_str());
            socket_.close();
            sessionSet_.erase(shared_from_this());
        }
    });
}
