#include"rules.h"



RULES::RULES()
{
	re_ALT = false;
}

RULES::~RULES()
{
	

}

int RULES::m_Rules_Loading()
{
	string name_signal = "";
	ADOConn m_adoConn;
	_bstr_t c = ".\\AllData.mdb";
	m_adoConn.OnInitADOConn(c);
	_bstr_t sql = "";
	sql = sql + "select * from RULS";
	_bstr_t strRecord;
	_RecordsetPtr m_pRecordset;
	m_pRecordset = m_adoConn.GetRecordSet((_bstr_t)sql);string temp_s;
	vector<string> CON;
	vector<string> RES;
	while (!m_pRecordset->adoEOF)
	{
		strRecord = (LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("ATTACWAY");
		name_signal = (string)strRecord;
		if (m_pRecordset->GetCollect("CONDITION1").vt != VT_NULL)
		{ 
			strRecord = (LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("CONDITION1");
			temp_s = (string)strRecord;
			Write_in(temp_s);
			CON.push_back(temp_s);
		}
		
		if (m_pRecordset->GetCollect("CONDITION2").vt != VT_NULL)
		{
			strRecord = (LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("CONDITION2");
			temp_s = (string)strRecord;
			Write_in(temp_s);
			CON.push_back(temp_s);
		}
		if (m_pRecordset->GetCollect("RESULT1").vt != VT_NULL)
		{
			strRecord = (LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("RESULT1");
			temp_s = (string)strRecord;
			Write_in(temp_s);
			RES.push_back(temp_s);
		}

		if (m_pRecordset->GetCollect("RESULT2").vt != VT_NULL)
		{
			strRecord = (LPCTSTR)(_bstr_t)m_pRecordset->GetCollect("RESULT2");
			temp_s = (string)strRecord;
			Write_in(temp_s);
			RES.push_back(temp_s);
		}
		
		for (int i = 0; i < RES.size(); i++)
		{
			
			list<Save_str> in_sum;
			for (int j = 0; j < CON.size(); j++)
			{
				in_sum.push_back(*save_index[Cheak(CON[j], 1)]);
				save_index[Cheak(CON[j], 1)]->address->outmaping.push_back(*save_index[Cheak(RES[i], 1)]);
			}
			save_index[Cheak(RES[i], 1)]->address->inmaping.push_back(in_sum);
			if (Cheak_CH0(RES[i]))
			{
				if (conf[name_signal].empty())
				{
					vector<string> ccc;
					ccc.push_back(RES[i]);
					conf[name_signal] = ccc;
					
				}
				else
				{
					conf[name_signal].push_back(RES[i]);
				}
			}
		}
		RES.clear();
		CON.clear();
		m_pRecordset->MoveNext();
		
	}
	for (auto io = conf.begin(); io != conf.end(); io++)
	{
		confilic.push_back((*io).second);
	}
	return 1;
}

bool RULES::xml_load_list(string add)
{

	tinyxml2::XMLDocument doc;
	string temp_model; string temp_type;
	if (tinyxml2::XML_SUCCESS != doc.LoadFile(add.c_str()))
	{
		cout << "load xml file failed!" << endl;
		return -1;
	}
	Detail_in_out temp;
	tinyxml2::XMLElement* root = doc.RootElement();
	tinyxml2::XMLElement* ptrNode_red = root->FirstChildElement();
	tinyxml2::XMLElement* ptrNode = ptrNode_red->FirstChildElement();
	temp_model = ptrNode->Attribute("Model");
	temp_type = ptrNode->Attribute("Type");
	model_index.push_back(temp_model);
	type_index.push_back(temp_type);
	ALL_type[temp_type].T_in.push_back(temp_type);
	ALL_type[temp_type].type = temp_type;
	ALL_model[temp_type][temp_model].type = temp_type;
	ALL_model[temp_type][temp_model].T_in.push_back(temp_type);
	while (ptrNode!= NULL)
	{
		temp.model = ptrNode->Attribute("Model");
		if (temp.model != temp_model)
		{
			//ALT_Classs new_classs;
			temp_model_index[temp_model] = temp_name_index;
			
			//new_classs.name = temp_model;
			//new_classs.num = temp_name_index.size();
			//data_info.push_back(new_classs);
			temp_name_index.clear();
			temp_model = temp.model;
			model_index.push_back(temp_model);
			ALL_model[ptrNode->Attribute("Type")][temp_model].type = ptrNode->Attribute("Type");
			ALL_model[ptrNode->Attribute("Type")][temp_model].T_in.push_back(ptrNode->Attribute("Type"));
		}
		temp.type = ptrNode->Attribute("Type");
		if (temp.type != temp_type)
		{
			if (ALL_show[temp_type].empty())
			{
				ALL_show[temp_type] = temp_model_index;
			}
			else
			{
				for (auto i = temp_model_index.begin(); i != temp_model_index.end(); i++)
				{
					ALL_show[temp_type][(*i).first] = (*i).second;
				}
				
			}
			temp_model_index.clear();
			ALT.push_back(temp_type);
			/*temp.T_in.clear();
			temp.T_in.push_back(ptrNode->Attribute("Type"));*/
			temp_type = temp.type;
			type_index.push_back(temp_type);
			ALL_type[temp_type].T_in.push_back(temp_type);
			ALL_type[temp_type].type = temp_type;
			
		}
		temp.T_in.push_back( temp_type);
		temp_name_index[ptrNode->Attribute("ID")] = temp;
		ptrNode = ptrNode->NextSiblingElement();
		temp.T_in.clear();
	}
	//ALT_Classs cccc;
	ALT.push_back(temp_type);
	temp_model_index[temp_model] = temp_name_index;
	
	/*cccc.name = temp_model;
	cccc.num = temp_name_index.size();
	data_info.push_back(cccc);*/
	if (ALL_show[temp_type].empty())
	{
		ALL_show[temp_type] = temp_model_index;
	}
	else
	{
		for (auto i = temp_model_index.begin(); i != temp_model_index.end(); i++)
		{
			ALL_show[temp_type][(*i).first] = (*i).second;
		}

	}
	return true;

}

void RULES::cout_select(string res, Detail_in_out& show)
{
	for (auto i = conf.begin(); i != conf.end(); i++)
	{
		if (Cheak((*i).second, res))
		{
			show.R_C_out[(*i).first].push_back(res);
		}
	}
}

void RULES::change_in(string in_data, Detail_in_out &all_in)
{
	string temp_c;
	vector<int> num;
	if (!CON_index[in_data].empty())
	{
		for (int i = 0; i < all_in.T_in.size(); i++)
		{
			temp_c = "*"+all_in.T_in[i];
			if (Cheak(CON_index[in_data], temp_c))
			{
				num.push_back(i);
			}
		}
		for (int j = num.size(); j >0; j--)
		{
			all_in.T_in.erase(all_in.T_in.begin() + (num[j-1]));
		}
	}
	else
	{
		return;
	}
}

void RULES::Write_in(string Name_T)
{

	if (Cheak(Name_T)==NULL)
	{
		map_in = new MAPing();
		map_in->value1 = Name_T;
		temp = new Save_str();
		temp->name = Name_T; temp->address = map_in;
		save_index.push_back(temp);
	}
	else
	{
		cout << "�Ѿ�������������" << endl;
	}

}

vector<string>  RULES::Call_Back(vector<string> &T_in)
{
	vector<string> temp_TIN = T_in;
	int num = T_in.size();
	vector<string> res;
	MAPing* temp_map;
	bool SUC;
	//vector<string> 
	//T_in.insert(T_in.end(), ALT.begin(), ALT.end());
	for (int i = 0; i < T_in.size(); i++)
	{
		temp_map = Cheak(T_in[i]);
		if (temp_map != NULL)
		{
			for (auto j = temp_map->outmaping.begin(); j != temp_map->outmaping.end(); ++j)
			{
				if (Cheak(res, (*j).name))
					continue;
				for (auto k = (*j).address->inmaping.begin(); k != (*j).address->inmaping.end();k++)
				{
					SUC = Cheak_O_in((*k), T_in);
					if (SUC)
						break;
				
				}
				if (SUC)
				{
					if(!Cheak(T_in, (*j).name))
						T_in.push_back((*j).name);
					if (!Cheak(ALT, (*j).name) && re_ALT&& (!Cheak_CH0((*j).name)))
					{

						ALT.push_back((*j).name);
					}
					res.push_back((*j).name);
					SUC = false;
				}
			}
		}
		else
		{
			continue;
			re_ALT = false;
			T_in = temp_TIN;
			return res;
		}
			
		
	}
	re_ALT = false;
	T_in = temp_TIN;
	return res;
}

bool RULES::Cheak_CH0(string ins)
{
	if (ins[0] == '*')
		return true;
	else 
		return false;
	
}

bool RULES::Cheak_Save(string name)
{
	string name_1 = "*" + name;
	for (int i = 0; i < save_index.size(); i++)
	{
		if (name == save_index[i]->name)
			return true;
		if(name_1 == save_index[i]->name)
			return true;
	}
	cout << "�������" << endl;
	return false;
	
}

bool RULES::Cheak_O_in(list<Save_str> T_list, vector<string>& T_in)
{
	bool panduan;
	int j;
	int cout = 0;
	vector<string> CON_SUM;
	CON_SUM = ALT;
	bool is_cor = false;
	for (auto i = T_list.begin(); i != T_list.end(); ++i)
	{
		if ((*i).name == "����Эͬ")
		{
			is_cor = true;
		}
	}
	if (is_cor)
	{
		CON_SUM = T_in;
	}
	else
	{
		CON_SUM.insert(CON_SUM.end(), T_in.begin(), T_in.end());
	}
	for (auto i = T_list.begin(); i != T_list.end(); ++i)
	{
		cout++;
		for ( j = 0; j < CON_SUM.size(); j++)
		{
			if ((*i).name == CON_SUM[j])
				break;
		}
		if (j == CON_SUM.size())
			return false;
		if (cout == T_list.size() )
			return true;
	}
	
}

void RULES::ALT_IN(string Alt)
{
	re_ALT = true;
	if (Cheak_Save(Alt))
	{
		ALT.push_back(Alt);
		run();
	}
	else 
	{
		return;
	}
	
}

void RULES::ALL_list_Tin(string type_name, string T_in)
{
	vector<string> temp_tin;
	vector<string> res;
	map<string ,vector<string>> copy_COUT;
	vector<string> copy_OUT;
	if (Cheak_Save(T_in))
	{
		change_in(T_in, ALL_type[type_name]);
		if (!Cheak(ALL_type[type_name].T_in, T_in))
			ALL_type[type_name].T_in.push_back(T_in);
		res = Call_Back(ALL_type[type_name].T_in);
		RES_select(res, ALL_type[type_name]);
	}
	if (Cheak_Save(T_in))
	{
		for (auto mod = ALL_model[type_name].begin(); mod != ALL_model[type_name].end(); mod++)
		{
			change_in(T_in, (*mod).second);
			if (!Cheak((*mod).second.T_in, T_in))
				(*mod).second.T_in.push_back(T_in);
			res = Call_Back((*mod).second.T_in);
			RES_select(res, (*mod).second);
		}
	}
	if(Cheak_Save(T_in))
	{ 
		for (auto i = ALL_show[type_name].begin(); i != ALL_show[type_name].end(); i++)
		{
			//temp_name_index = (*i).second;
			for (auto j = (*i).second.begin(); j != (*i).second.end(); j++)
			{
				change_in(T_in, (*j).second);
				if (!Cheak((*j).second.T_in, T_in))
					(*j).second.T_in.push_back(T_in);
				if (temp_tin.empty())
				{
					temp_tin = (*j).second.T_in;
					res = Call_Back(temp_tin);
					RES_select(res, (*j).second);
					copy_COUT = (*j).second.R_C_out;
					copy_OUT = (*j).second.R_out;
				}
				else
				{
					if (temp_tin == (*j).second.T_in)
					{
						(*j).second.R_C_out = copy_COUT;
						(*j).second.R_out = copy_OUT;
					}
					else
					{
						temp_tin = (*j).second.T_in;
						res = Call_Back(temp_tin);
						RES_select(res, (*j).second);
						copy_COUT = (*j).second.R_C_out;
						copy_OUT = (*j).second.R_out;
					}
				}
			}
		}
	//RES_select(res, modelname);����ע��
	}
	else
	{
		return;
	}
}

void RULES::ALL_list_Tin(string type_name, string model_name, string T_in)
{
	vector<string> temp_tin;
	vector<string> res;
	map<string, vector<string>> copy_COUT;
	vector<string> copy_OUT;
	if (Cheak_Save(T_in))
	{
		change_in(T_in, ALL_model[type_name][model_name]);
		if (!Cheak(ALL_model[type_name][model_name].T_in, T_in))
			ALL_model[type_name][model_name].T_in.push_back(T_in);
		res = Call_Back(ALL_model[type_name][model_name].T_in);
		RES_select(res, ALL_model[type_name][model_name]);
	}
	if (Cheak_Save(T_in))
	{
		for (auto j = ALL_show[type_name][model_name].begin(); j != ALL_show[type_name][model_name].end(); j++)
		{
			change_in(T_in, (*j).second);
			if (!Cheak((*j).second.T_in, T_in))
				(*j).second.T_in.push_back(T_in);
			if (temp_tin.empty())
			{
				temp_tin = (*j).second.T_in;
				res = Call_Back(temp_tin);
				RES_select(res, (*j).second);
				copy_COUT = (*j).second.R_C_out;
				copy_OUT = (*j).second.R_out;
			}
			else
			{
				if (temp_tin == (*j).second.T_in)
				{
					(*j).second.R_C_out = copy_COUT;
					(*j).second.R_out = copy_OUT;
				}
				else
				{
					temp_tin = (*j).second.T_in;
					res = Call_Back(temp_tin);
					RES_select(res, (*j).second);
					copy_COUT = (*j).second.R_C_out;
					copy_OUT = (*j).second.R_out;
				}
			}
		}
	}
	else
	{
		return;
	}
}

void RULES::ALL_list_Tin(string type_name, string model_name, string name, string T_in)
{
	vector<string> res;
	change_in(T_in, ALL_show[type_name][model_name][name]);
	if (!Cheak(ALL_show[type_name][model_name][name].T_in, T_in))
		ALL_show[type_name][model_name][name].T_in.push_back(T_in);
	res = Call_Back(ALL_show[type_name][model_name][name].T_in);
	RES_select(res, ALL_show[type_name][model_name][name]);
		
}

void RULES::RULS_Init(string Address,  map<std::string, ABILITY*> fdb)
{
	ALT_Classs init;
	Detail_in_out temp_in_out;
	xml_load_list(Address);
	m_Rules_Loading();
	re_ALT = true;
	for (int beg = 0; beg < data_info.size(); beg++)
	{
		
		if ((data_info[beg].name).empty())
		{
			data_info[beg].AttackAbility = fdb[data_info[beg].name]->AttackAbility;
			data_info[beg].DetectAbility = fdb[data_info[beg].name]->DetectAbility;
			data_info[beg].InterfereAbility = fdb[data_info[beg].name]->InterfereAbility;
			data_info[beg].SurAbility = fdb[data_info[beg].name]->SurAbility;
		}
	}
	
	run();
	/*if (!ALL_show["Attacker"].empty())
		{
			ALL_list_Tin("Attacker","���˻�����Эͬ");
		}
	if (!ALL_show["AWACS"].empty())
	{
		ALL_list_Tin("AWACS", "Ԥ��������Эͬ");
	}*/
}



bool RULES::Empty(int c_in)
{
	if (c_in != 0)
		return true;
	else	
		return false;
}



void RULES::run()
{
	conf_cheak();
	vector<string> res;
	vector<string> temp_tin;
	map<string, vector<string>> copy_COUT;
	vector<string> copy_OUT;
	if (re_ALT)
	{
		vector<string> alt_temp = ALT;
		Call_Back(alt_temp);
		alt_temp.clear();//�ܽ��չʾ����
	}
	for (auto ty = ALL_type.begin(); ty != ALL_type.end(); ty++)
	{
		res = Call_Back((*ty).second.T_in);
		RES_select(res, (*ty).second);

	}
	for (auto mod = ALL_model.begin(); mod != ALL_model.end(); mod++)
	{
		for (auto mod1 = (*mod).second.begin(); mod1 != (*mod).second.end(); mod1++)
		{
			res = Call_Back((*mod1).second.T_in);
			RES_select(res, (*mod1).second);
		}

	}
	for (int q = 0; q < type_index.size(); q++)
	{
		for (auto i = ALL_show[type_index[q]].begin(); i != ALL_show[type_index[q]].end(); i++)
		{
			//temp_name_index = (*i).second;
			for (auto j = (*i).second.begin(); j != (*i).second.end(); j++)
			{
				if (temp_tin.empty())
				{
					temp_tin = (*j).second.T_in;
					res = Call_Back(temp_tin);
					RES_select(res, (*j).second);
					copy_COUT = (*j).second.R_C_out;
					copy_OUT = (*j).second.R_out;
				}
				else
				{
					if (temp_tin == (*j).second.T_in)
					{
						(*j).second.R_C_out = copy_COUT;
						(*j).second.R_out = copy_OUT;
					}
					else
					{
						temp_tin = (*j).second.T_in;
						res = Call_Back(temp_tin);
						RES_select(res, (*j).second);
						copy_COUT = (*j).second.R_C_out;
						copy_OUT = (*j).second.R_out;
					}
				}
			}
		}
	}
}


RULES* RULES::Create_RULES()
{
	RULES* temp = NULL;
	temp = new RULES();
	return temp;
	
}

MAPing* RULES::Cheak(string Name_T)
{
	for (int i = 0; i < save_index.size(); i++)
	{
		if (save_index[i]->name == Name_T)
			return save_index[i]->address;
	}
	return NULL;
}

int RULES::Cheak(vector<string> Name_v, string Name_T, int model)
{
	for (int i = 0; i < Name_v.size(); i++)
	{
		if (Name_v[i] == Name_T)
			return i;
	}
	return -1;
}


int RULES::Cheak(string Name_T, int model)
{
	for (int i = 0; i < save_index.size(); i++)
	{
		if (save_index[i]->name == Name_T)
			return i;
	}
	return -1;
}

void RULES::RES_select(vector<string> res, Detail_in_out &id)
{
	id.R_C_out.clear();
	id.R_out.clear();
	vector<string>temp;
	/*string bbb = "";
	string is_xie = "";
	if(id.type!="")
		 bbb = id.type.substr(id.type.size() - 3, 3);*/
	vector<int> num;
	for (int i = 0; i < res.size(); i++)
	{
		/*is_xie = res[i].substr(res[i].size() - 4, 4);
		if (bbb == "Uav" && (is_xie == "Эͬ"))
			continue;*/
		if (Cheak_CH0(res[i]))
			cout_select(res[i], id);
		else
			id.R_out.push_back(res[i]);
	}
	
}

bool RULES::Cheak(vector<string> Name_V, string name)
{
	for (int i = 0; i < Name_V.size(); i++)
	{
		if (Name_V[i] == name)
			return true;
	}
	return false;
}

vector<string> RULES::Cheak_cof(string conf)
{
	string temp = "*";
	temp = temp + conf;
	vector<string> R_conf;
	for (int i = 0; i < confilic.size(); i++)
	{
		for (int j = 0; j < confilic[i].size(); j++)
		{
			if (temp == confilic[i][j])
			{
				R_conf.insert(R_conf.end(), confilic[i].begin(), confilic[i].end());
				break;
			}
		}
	}
	return R_conf;
	
}

void RULES::conf_cheak()
{
	vector<string> temp_c;
	for (auto i = save_index.begin(); i != save_index.end(); i++)
	{
		temp_c = (Cheak_cof((*i)->name));
		if (temp_c.size()>0)
		{
			//CON_index[(*i)->name] = Cheak_cof((*i)->name);
			for (int j = 0; j < temp_c.size(); j++)
			{
				string name = temp_c[j];
				name = name.substr(1, name.size() - 1);
				if (CON_index[name].empty())
				{
					CON_index[name] = Cheak_cof((*i)->name);
				}
				
			}
		}
	
	}
}



bool RULES::delect_ALT_IN(string Alt)
{
	vector<string> temp;
	vector<string> temp_alt;
	temp_alt.push_back(Alt);
	for (int te = 0; te < model_index.size(); te++)
	{
		if (model_index[te] == Alt)
		{
			cout << "ɾ������" << endl;
			return false;
		}
	}
	vector<int> num;
	if (Cheak(ALT, Alt))
	{
		temp = Call_Back(temp_alt);
		if(!Cheak(temp,Alt))
			temp.push_back(Alt);
		for (int i = 0; i < temp.size(); i++)
		{
			if (Cheak(ALT, temp[i]))
			{
				num.push_back(Cheak(ALT, temp[i],1));
			}
		}
		for (int l = num.size(); l > 0; l--)
			ALT.erase(ALT.begin() + num[l - 1]);
		re_ALT = true;
		run();
		return true;
	}
	else
	{
		return false;
	}
}