#include "tcp_server_form.h"
#include "utils.h"
#include <functional>
#include "lua_bind.h"
#include "msgdef.h"
extern  "C" {
#include "event2/bufferevent.h"
#include "event2/buffer.h"
#include "event2/listener.h"
#include "event2/util.h"
#include "event2/event.h"
#include "event2/thread.h"
};


#define TCP_SERVER_SCRIPT   "tcp_server.lua"
TcpServerFrom::~TcpServerFrom() {

}


TcpServerFrom::TcpServerFrom(ui::Window* hwnd, string url,
	uint32_t port, TcpServerLibevent* p):
	mLua(nullptr)
{
	m_server = p;
	m_url = url;
	m_port = port;
	mFlagSelectClient = true;

	mLua = new LuaDelegate;
	mLuaFileRead.open(TCP_SERVER_SCRIPT);
	std::string lua_script;
	if (mLuaFileRead.is_open()) {
		std::string s;
		while (getline(mLuaFileRead, s)) {
			lua_script += s + "\r\n";
		}
		mLuaFileRead.close();
	}
	mLuaScript = lua_script;
	mLua->DoString(lua_script);
	std::cout << "lua script is " << lua_script << std::endl;

	TcpServerLibevent::OnAccept handler = std::bind(&TcpServerFrom::OnNewConnAccept, this,std::placeholders::_1 );
	m_server->SetNewConnectionHandle(handler);
	TcpServerLibevent::OnDisconnect handler2 = std::bind(&TcpServerFrom::OnDisConnected,
		this, std::placeholders::_1);
	m_server->SetConnectionLeaveHandle(handler2);
	this->mLua->BindFunction("showdata", LuaShowData);
}


TcpServerLibevent* TcpServerFrom::ServerP()
{
	return this->m_server;
}

void TcpServerFrom::Init()
{
	ui::ChildBox::Init();  // �dz���Ҫ,û���º�childbox �����FindSubControl�޷���Ч

	m_label_1 = dynamic_cast<ui::Label*>(FindSubControl(L"server_info"));
	m_rich_edit_1 = dynamic_cast<ui::RichEdit*>(FindSubControl(L"server_recv_edit"));
	mEditLua = dynamic_cast<ui::RichEdit*>(FindSubControl(L"lua_script_edit"));
	mEditLua->SetRich(true);
	mEditLua->SetReturnMsgWantCtrl(true);

	mEditLua->SetText(string2wstring(mLuaScript));

	m_rich_edit_3 = dynamic_cast<ui::RichEdit*>(FindSubControl(L"server_send_edit"));
	m_button_1 = dynamic_cast<ui::Button*>(FindSubControl(L"btn_send_data"));
	m_check_box_2 = dynamic_cast<ui::CheckBox*>(FindSubControl(L"check_time_send"));
	m_rich_edit_4 = dynamic_cast<ui::RichEdit*>(FindSubControl(L"cycle_eidt"));
	m_check_box_3 = dynamic_cast<ui::CheckBox*>(FindSubControl(L"check_hex_send"));
	m_check_box_4 = dynamic_cast<ui::CheckBox*>(FindSubControl(L"check_hex_recv"));
	m_button_2 = dynamic_cast<ui::Button*>(FindSubControl(L"btn_close_uart"));
	m_label_2 = dynamic_cast<ui::Label*>(FindSubControl(L"title"));
	m_combo_1 = dynamic_cast<ui::Combo*>(FindSubControl(L"clients"));
	m_button_3 = dynamic_cast<ui::Button*>(FindSubControl(L"btn_do_lua"));
	m_btn_save_lua = dynamic_cast<ui::Button*>(FindSubControl(L"btn_save_lua"));

	if (m_button_2 != nullptr) {
		m_button_2->AttachClick([this](ui::EventArgs* ev) {
			wstring* name = new wstring(this->GetName());
			::PostMessage(this->GetWindow()->GetHWND(),
				WM_USER_TCP_SERVER_CLOSE, (WPARAM)name, 0);

			return true;
		});
	}

	if (nullptr != m_button_1) {
		m_button_1->AttachClick([this](ui::EventArgs* ev) {
			auto client = m_combo_1->GetText();
			if (client != L"ȫ������") {
				int clii = atoi(wstring2string(client).c_str());
				if (nullptr != this->mClients[clii]) {
					std::wstring send = m_rich_edit_3->GetText();
					this->mClients[clii]->WriteData(wstring2string(send).c_str(), 
						wstring2string(send).size());
				}
			}
			else {
				if ((nullptr != m_rich_edit_3)) {
					std::wstring send = m_rich_edit_3->GetText();
					for (auto itr = this->mClients.begin(); itr != this->mClients.end(); itr++) {
						itr->second->WriteData(wstring2string(send).c_str(),
							wstring2string(send).size());
					}
				}
			}
			return true;
		});
	}
	
	m_btn_save_lua->AttachClick([this](ui::EventArgs* ev) {
		std::cout << "����lua�ű�\r\n";
		std::string lua = wstring2string(mEditLua->GetText());
		if (0 == this->mLua->UpdateScript(lua)) {
			this->mLuaScript = lua;
			mLuaFileEdit = std::ofstream(TCP_SERVER_SCRIPT, std::ios::out | std::ios::trunc);
			mLuaFileEdit.write(lua.c_str(), lua.size());
			mLuaFileEdit.flush();
			mLuaFileEdit.close();
		}
		else {
			MessageBox(0, L"lua�ű�����", L"", 0);
			return true;
		}
		std::cout << lua.c_str() << "\r\n";
		return true;
	});

	m_button_3->AttachClick([this](ui::EventArgs*ev) {
		std::cout <<"m_button_3 " << wstring2string(this->m_combo_1->GetText())<<std::endl;
		return true;
	});
	wchar_t p[200] = L"";
	wsprintf(p,L"������ַ: %s �˿�: %d ����������Ŀ: %d",string2wstring(m_url).c_str(),
		m_port,
		m_server->ConnectionCount());
	m_label_1->SetText(p);

	auto element = new ui::ListContainerElement;
	element->SetClass(L"listitem");
	element->SetFixedHeight(30);
	element->SetBkColor(L"white");
	element->SetTextPadding({ 6,0,6,0 });
	element->SetText(L"ȫ������");
	m_combo_1->Add(element);

}

void TcpServerFrom::OnNewConnAccept(ConnectionLibevent* p)
{
	std::cout << "TcpServerFrom OnNewConnAccept addr " << p->IpAddress() << p->SocketFd() << std::endl;
	updateStatus();
	int ret = mLua->CallFuntion < std::string, LUA_INTEGER >("OnNewClient",p->IpAddress(),p->SocketFd());
	if (ret < 0) {
		std::cout << "call funtion error" << ret<<"std::endl";
	}
	auto element = new ui::ListContainerElement;
	element->SetClass(L"listitem");
	element->SetFixedHeight(30);
	element->SetBkColor(L"white");
	element->SetTextPadding({ 6,0,6,0 });
	element->SetText(std::to_wstring(p->SocketFd()));
	mClients[p->SocketFd()] = p;
	m_combo_1->Add(element);
	p->SetRecvHandler(
		[this,p](char* recv, uint32_t len) {
			std::cout << "RecvHandler "<<p->IpAddress()<<p->SocketFd() <<" " << recv;
			int ret = this->mLua->CallFuntion <std::string,std::string,LUA_INTEGER >
				("OnClientRecvData", std::string(recv),p->IpAddress(), p->SocketFd());
			if (ret < 0) {
				MessageBox(0, L"lua�ű����� OnClientRecvData", L"", 0);
			}
		}
	);
	return;
}

void TcpServerFrom::OnDisConnected(ConnectionLibevent* cli)
{
	std::cout << "TcpServerFrom Disconnected" << cli->IpAddress() << " fd " << cli->SocketFd() << std::endl;
	updateStatus();
	mClients.erase(cli->SocketFd());
	int ret = this->mLua->CallFuntion <std::string, LUA_INTEGER >
		("OnClientDisconnect", cli->IpAddress(), cli->SocketFd());
	if (ret < 0) {
		MessageBox(0, L"lua�ű����� OnClientRecvData", L"", 0);
	}
}

LuaDelegate* TcpServerFrom::LuaVM()
{
	return mLua;
}

void TcpServerFrom::ShowDataInEdit(const char* value)
{
	if (nullptr == value) {
		std::cout << "nullp pointer in ShowDataInEdit" << std::endl;
		return;
	}
	m_rich_edit_1->AppendText(string2wstring(std::string(value)));
}

void TcpServerFrom::updateStatus()
{
	wchar_t tmp[200] = L"";
	wsprintf(tmp, L"������ַ: %s �˿�: %d ����������Ŀ: %d", string2wstring(m_url).c_str(),
		m_port,
		m_server->ConnectionCount());
	m_label_1->SetText(tmp);
}