#include "SQLAPI.h"
#include <vector>
//#include <easylogging++.h>
#include <epm/epm_toolkit_tc_utils.h>
#include <tc/preferences.h>
#include <tccore/aom_prop.h>
#include <tccore/iman_grmtype.h>
#include <tccore/grm.h>
#include <tccore/item.h>
#include <rapidjson/document.h>
#include <bom/bom.h>
#include <sstream>
#include <iostream>
#include "tx_erp_bom.h"
#include "erp_send_item.h"

using namespace  std;

struct obj
{
	tag_t item;
	tag_t rev;
	tag_t form;
	tag_t bom;
};

class db
{
private:
	vector<string> key, val;
public:
	SACommand *command;
	SADateTime sql_time;
	logical kong;
	void add(string a, string b)
	{
		key.push_back(a);
		val.push_back(b);
	}
	logical search(char * table)
	{
		if (key.size() != val.size())
			return false;

		stringstream ss;
		ss << "select * from " << table << " where ";
		for (auto i = 0; i < key.size(); i++)
		{
			
				
			ss << key[i];
			ss << "='";
				ss << val[i];
				
				if (i != key.size()-1)
				{
						ss << "' and ";
				}else
				{
					ss << "' ";
				}
		}
			



	
		cout<<"插入语句---------"<<ss.str().c_str()<<endl;
		try
		{
			(*command).setCommandText(ss.str().c_str());

			(*command).Execute();
			kong=true;
			while ((*command).FetchNext())
			{
				
				key.clear();
				val.clear();
				return false;
			}
			
		}
		catch (SAException e)
		{
			printf("error:%s\n", e.ErrMessage().GetMultiByteChars());

		}
		return true;
	};
	void insert(char * table)
	{
		if (key.size() != val.size())
			return;

		stringstream ss;
		ss << "insert into " << table << "(";
		for (auto i = 0; i < key.size(); i++)
		{
			if (i != 0)
				ss << ',';
			ss << key[i];
		}
		ss << ") values(";
		for (auto i = 1; i <= key.size(); i++)
		{
			if (i != 1)
				ss << ',';
			ss << ':' << i;
		}
		ss << ')';
		cout<<"插入语句---------"<<ss.str().c_str()<<endl;
		try
		{
			(*command).setCommandText(ss.str().c_str());
			for (auto i = 0; i < val.size(); i++)
			{
				if (val[i] == "now:")
				{
					*command << sql_time;
				}
				else
					*command << val[i].c_str();
			}
			(*command).Execute();
		}
		catch (SAException e)
		{
			printf("error:%s\n", e.ErrMessage().GetMultiByteChars());

		}
		key.clear();
		val.clear();
	};
	string guid()
	{
		string result;
		try
		{
			command->setCommandText("select sys_guid() from dual");
			command->Execute();
			if (command->FetchNext())
			{
				result = command->Field(1).asString();
			}
		}
		catch (SAException e)
		{
			printf("error:%s\n", e.ErrMessage().GetMultiByteChars());
		}
		return result;
	}
		void put(string db_key, string prop, char c, obj & o)
	{
		tag_t tag = NULLTAG;
		switch (c)
		{
		case 'I':tag = o.item;
			break;
		case 'B':tag = o.bom;
			break;
		case 'R':tag = o.rev;
			break;
		case 'F':tag = o.form;
			break;
		default:
			break;
		}
		if (tag == NULLTAG)
			return;
		//2020.03.01 如果是不存在的属性，就要穿空
		char *val=NULL;
		AOM_UIF_ask_value(tag, prop.c_str(), &val);	
		
		

	
		
		
		//2019.12.31 如果传的字段是TX_BOM_LIST_NO，要特殊处理下
		if(strcmp(db_key.c_str(),"TX_BOM_LIST_NO")==0)
		{
			tag = o.form;
			char *val_id=NULL;
			vector<string> idVec;
			AOM_UIF_ask_value(tag, "object_name", &val_id);//
			string idString=val_id;
			Split(idString,"/",idVec);
			string newlongcode=idVec[0];
			char *val_long=NULL;
			AOM_UIF_ask_value(tag, "tx2MaterialLongCode", &val_long);//
			idString=val_long;
			Split(idString,"\.",idVec);
			string index="";
			for(int i=0;i<idVec.size()-1;i++)
			{
				index=index+idVec[i]+".";
			}
			index=index+newlongcode;
			if(val_id!=NULL)
			{
				MEM_free(val_id);
				val_id=NULL;
			}	
			if(val_long!=NULL)
			{
				MEM_free(val_long);
				val_long=NULL;
			}
			add(db_key, index);
		}else
		{
			if(val==NULL)
			{
				add(db_key, "");
			}else
			{
				add(db_key, val);
			}
			
		}
		
		if(val!=NULL)
		{
			MEM_free(val);
			val=NULL;
		}
		
		
	}


	void put(string db_key, string prop, char c, obj & o,string wrongType)
	{
		tag_t tag = NULLTAG;
		switch (c)
		{
		case 'I':tag = o.item;
			break;
		case 'B':tag = o.bom;
			break;
		case 'R':tag = o.rev;
			break;
		case 'F':tag = o.form;
			break;
		default:
			break;
		}
		if (tag == NULLTAG)
			return;
		//2020.03.01 如果是不存在的属性，就要穿空
		char *val=NULL;
		char *oType=NULL;
		AOM_ask_value_string(tag,"object_type",&oType);
		cout<<oType<<endl;
		if(strstr(wrongType.c_str(),oType)==NULL)
		{
				cout<<"7------"<<endl;
			AOM_UIF_ask_value(tag, prop.c_str(), &val);	
		}
		

	
		
		
		//2019.12.31 如果传的字段是TX_BOM_LIST_NO，要特殊处理下
		if(strcmp(db_key.c_str(),"TX_BOM_LIST_NO")==0)
		{
			tag = o.form;
			char *val_id=NULL;
			vector<string> idVec;
			AOM_UIF_ask_value(tag, "object_name", &val_id);//
			string idString=val_id;
			Split(idString,"/",idVec);
			string newlongcode=idVec[0];
			char *val_long=NULL;
			AOM_UIF_ask_value(tag, "tx2MaterialLongCode", &val_long);//
			idString=val_long;
			Split(idString,"\.",idVec);
			string index="";
			for(int i=0;i<idVec.size()-1;i++)
			{
				index=index+idVec[i]+".";
			}
			index=index+newlongcode;
			if(val_id!=NULL)
			{
				MEM_free(val_id);
				val_id=NULL;
			}	
			if(val_long!=NULL)
			{
				MEM_free(val_long);
				val_long=NULL;
			}
			add(db_key, index);
		}else
		{
			if(val==NULL)
			{
				add(db_key, "");
			}else
			{
				add(db_key, val);
			}
			
		}
		
		if(val!=NULL)
		{
			MEM_free(val);
			val=NULL;
		}
		if(oType!=NULL)
		{
			MEM_free(oType);
			oType=NULL;
		}
		
	}

};

char * get_val(tag_t tag, char *name)
{
	char *val;
	AOM_UIF_ask_value(tag, name, &val);
	return val;
}

bool isTypeOf(tag_t objtag, const char * type_name) {
	tag_t type = NULLTAG;
	TCTYPE_ask_object_type(objtag, &type);
	tag_t item_type = NULLTAG;
	TCTYPE_find_type(type_name, "", &item_type);
	bool is_type = false;
	if (item_type != NULLTAG) {
		logical isok = FALSE;
		TCTYPE_is_type_of(type, item_type, &isok);
		if (isok) {
			is_type = true;
		}
	}
	return is_type;
}

int erp(tag_t task,vector<tag_t> attatcgments2)
{
	tag_t root_task, *atts, relation_type, *rels;
	int pref_cnt, n_cnt, rel_cnt;
	char **pref_values;
	db db;
	time_t t = time(0);
	tm* local = localtime(&t);
	db.sql_time = *local;
	SAConnection conn;
	SACommand command;
	PREF_ask_char_values("tx_AutoSign_DB_Configer", &pref_cnt, &pref_values);
	stringstream ss;
	ss << pref_values[0] << ':' << pref_values[1] << '/' << pref_values[3];
	conn.Connect(pref_values[3], pref_values[0], pref_values[1],
		SA_Oracle_Client);
	conn.setAutoCommit(SA_AutoCommitOff);
	command.setConnection(&conn);
	db.command = &command;
	EPM_ask_root_task(task, &root_task);
	EPM_ask_attachments(root_task, EPM_target_attachment, &n_cnt, &atts);
	GRM_find_relation_type(IMAN_master_form_rtype, &relation_type);
	rapidjson::Document doc;
	PREF_ask_char_values("TX_ERP_TC_PROPERTY", &pref_cnt, &pref_values);
	// cout<<pref_values[0]<<endl;
	doc.Parse(pref_values[0]);
	for (int i=0;i<attatcgments2.size();i++)
	{
		if (isTypeOf(attatcgments2[i], "ItemRevision"))
		{
			tag_t item;
			tag_t form;
			ITEM_ask_item_of_rev(attatcgments2[i], &item);
			GRM_list_secondary_objects_only(attatcgments2[i], relation_type, &rel_cnt, &rels);
			form = rels[0];
			obj o;
			o.item = item;
			o.rev = attatcgments2[i];
			o.form = form;
			for (rapidjson::SizeType j = 0; j < doc.Size(); j++)
			{
				
				string wrongType="";
				try
				{
					wrongType=doc[j]["EXP"].GetString();
				}
				catch (...)
				{
				}
				if(wrongType.length()>0)
				{
					db.put(doc[j]["ERP"].GetString(), doc[j]["TC"].GetString(), doc[j]["TYPE"].GetString()[0], o,wrongType);
				}else
				{
					db.put(doc[j]["ERP"].GetString(), doc[j]["TC"].GetString(), doc[j]["TYPE"].GetString()[0], o);
				}
				
			}
			db.add("creation_date", "now:");
			db.add("process_status", "1");

			db.insert("TX_PART_INFO_TABLE");
		}


	}
	for (int i = 0; i < n_cnt; i++)
	{
		if (isTypeOf(atts[i], "ItemRevision"))
		{
			tag_t item;
			tag_t form;
			ITEM_ask_item_of_rev(atts[i], &item);
			GRM_list_secondary_objects_only(atts[i], relation_type, &rel_cnt, &rels);
			form = rels[0];
			obj o;
			o.item = item;
			o.rev = atts[i];
			o.form = form;
			for (rapidjson::SizeType j = 0; j < doc.Size(); j++)
			{
				//判断下是否在包含的类型中，如果是，就跳过
				string wrongType="";
				try
				{
					wrongType=doc[j]["EXP"].GetString();
				}
				catch (...)
				{
				}
				if(wrongType.length()>0)
				{
					db.put(doc[j]["ERP"].GetString(), doc[j]["TC"].GetString(), doc[j]["TYPE"].GetString()[0], o,wrongType);
				}else
				{
					db.put(doc[j]["ERP"].GetString(), doc[j]["TC"].GetString(), doc[j]["TYPE"].GetString()[0], o);
				}
			}
			db.add("creation_date", "now:");
			db.add("process_status", "1");

			db.insert("TX_PART_INFO_TABLE");
		}
	}


	try
	{
		conn.Commit();
	}
	catch (SAException e)
	{
		try
		{
			conn.Rollback();
		}
		catch (SAException)
		{
		}
		printf("error:%s\n", e.ErrMessage().GetMultiByteChars());
	}
	conn.Disconnect();
	return 0;
}

int tx_erp(EPM_action_message_t msg)
{
	vector<tag_t> vector;
	erp(msg.task,vector);
	return 0;
}

void bom_loop(tag_t win,tag_t relation_type,tag_t top_line,char** pref_values,db db)
{
	rapidjson::Document doc,doc2;
	doc.Parse(pref_values[1]);//TX_BOM_TABLE
	doc2.Parse(pref_values[2]);//TX_BOM_LINE
	tag_t    *rels;
	
	int line_cnt,rel_cnt;
	tag_t *lines=NULLTAG;
	BOM_line_ask_child_lines(top_line, &line_cnt, &lines);
	if(line_cnt>0)
	{
		string puid = db.guid();//数据库生成一个uid
		tag_t p_rev, p_item,c_rev,c_item;
		obj p_obj;

		AOM_ask_value_tag(top_line, "bl_line_object", &p_rev);
		ITEM_ask_item_of_rev(p_rev, &p_item);
		GRM_list_secondary_objects_only(p_rev, relation_type, &rel_cnt, &rels);
		p_obj.form = rels[0];
		p_obj.item = p_item;
		p_obj.rev = p_rev;
		p_obj.bom = top_line;
		for (rapidjson::SizeType j = 0; j < doc.Size(); j++)
		{
			
			db.put(doc[j]["ERP"].GetString(), doc[j]["TC"].GetString(), doc[j]["TYPE"].GetString()[0], p_obj);
		}
		//先查询下TX_BOM_TABLE有无这条数据，有的话，跳过并清空key和value
		logical hasData=db.search("TX_BOM_TABLE");
		if(hasData==false)
		{
			if(lines!=NULL)
			{
				MEM_free(lines);
				lines=NULL;
			}
			if(rels!=NULL)
			{
				MEM_free(rels);
				rels=NULL;
			}
			return;
		}
		db.add("TX_PID", puid);
		db.add("TX_BOM_CREATION_DATE", "now:");
		db.add("TX_BOM_PROCESS_STATUS", "1");
		db.insert("TX_BOM_TABLE");

		

		for(int j=0;j<line_cnt;j++)
		{
			AOM_ask_value_tag(lines[j], "bl_line_object", &c_rev);
			ITEM_ask_item_of_rev(c_rev, &c_item);
			GRM_list_secondary_objects_only(c_rev, relation_type, &rel_cnt, &rels);
			obj c_obj;
			c_obj.rev = c_rev;
			c_obj.item = c_item;
			c_obj.bom = lines[j];
			c_obj.form = rels[0];
			for (rapidjson::SizeType k = 0; k< doc2.Size(); k++)
			{
				
				db.put(doc2[k]["ERP"].GetString(), doc2[k]["TC"].GetString(), doc2[k]["TYPE"].GetString()[0], c_obj);
			}
			db.add("TX_PID", puid);
			db.add("TX_BOM_CREATION_DATE", "now:");
			db.add("TX_BOM_PROCESS_STATUS", "1");
			db.insert("TX_BOM_LINE");
			int line_cnt2=0;
			tag_t *lines2=NULLTAG;
			BOM_line_ask_child_lines(lines[j], &line_cnt2, &lines2);
			if(line_cnt2>0)
			{
				bom_loop( win, relation_type,lines[j], pref_values,db);
			}
			if(lines2!=NULL)
			{
				MEM_free(lines2);
				lines2=NULL;
			}
			if(rels!=NULL)
			{
				MEM_free(rels);
				rels=NULL;
			}
		}
	}

	if(lines!=NULL)
	{
		MEM_free(lines);
		lines=NULL;
	}



	
}

void erp_bom(tag_t task)
{
	tag_t root_task, *atts=NULLTAG, relation_type, *rels=NULLTAG,win,top_line;
	
	int pref_cnt=0, n_cnt, rel_cnt;
	char **pref_values=NULL;
	db db;
	time_t t = time(0);
	tm* local = localtime(&t);
	db.sql_time = *local;
	SAConnection conn;
	SACommand command;
	PREF_ask_char_values("tx_AutoSign_DB_Configer", &pref_cnt, &pref_values);
	
	stringstream ss;
	ss << pref_values[0] << ':' << pref_values[1] << '/' << pref_values[3];
	conn.Connect(pref_values[3], pref_values[0], pref_values[1],
		SA_Oracle_Client);
	conn.setAutoCommit(SA_AutoCommitOff);
	command.setConnection(&conn);
	db.command = &command;
	EPM_ask_root_task(task, &root_task);
	EPM_ask_attachments(root_task, EPM_target_attachment, &n_cnt, &atts);
	GRM_find_relation_type(IMAN_master_form_rtype, &relation_type);
	
	rapidjson::Document doc,doc2;
	PREF_ask_char_values("TX_ERP_TC_PROPERTY", &pref_cnt, &pref_values);//TODO 获取首选项
	doc.Parse(pref_values[1]);//TX_BOM_TABLE
	doc2.Parse(pref_values[2]);//TX_BOM_LINE
	BOM_create_window(&win);


	//2020.01.01 传递所有层级
	for(int i=0;i<n_cnt;i++)
	{
		if(isTypeOf(atts[i],"PSBOMViewRevision"))
		{
			BOM_set_window_top_line_bvr(win, atts[i], &top_line);
			bom_loop(win,relation_type,top_line, pref_values,db);
			/*int line_cnt;
			tag_t *lines;
			BOM_line_ask_child_lines(top_line, &line_cnt, &lines);
			string puid = db.guid();//数据库生成一个uid
			tag_t p_rev, p_item,c_rev,c_item;
			obj p_obj;
			
			AOM_ask_value_tag(top_line, "bl_line_object", &p_rev);
			ITEM_ask_item_of_rev(p_rev, &p_item);
			GRM_list_secondary_objects_only(p_rev, relation_type, &rel_cnt, &rels);
			p_obj.form = rels[0];
			p_obj.item = p_item;
			p_obj.rev = p_rev;
			p_obj.bom = top_line;
			for (rapidjson::SizeType j = 0; j < doc.Size(); j++)
			{
				db.put(doc[j]["ERP"].GetString(), doc[j]["TC"].GetString(), doc[j]["TYPE"].GetString()[0], p_obj);
			}
			db.add("TX_PID", puid);
			db.add("TX_BOM_CREATION_DATE", "now:");
			db.add("TX_BOM_PROCESS_STATUS", "1");
			db.insert("TX_BOM_TABLE");




			for(int j=0;j<line_cnt;j++)
			{
				AOM_ask_value_tag(lines[j], "bl_line_object", &c_rev);
				ITEM_ask_item_of_rev(c_rev, &c_item);
				GRM_list_secondary_objects_only(c_rev, relation_type, &rel_cnt, &rels);
				obj c_obj;
				c_obj.rev = c_rev;
				c_obj.item = c_item;
				c_obj.bom = lines[j];
				c_obj.form = rels[0];
				for (rapidjson::SizeType k = 0; k< doc2.Size(); k++)
				{
					db.put(doc2[k]["ERP"].GetString(), doc2[k]["TC"].GetString(), doc2[k]["TYPE"].GetString()[0], c_obj);
				}
				db.add("TX_PID", puid);
				db.add("TX_BOM_CREATION_DATE", "now:");
				db.add("TX_BOM_PROCESS_STATUS", "1");
				db.insert("TX_BOM_LINE");
			}
				if(lines!=NULL)
				{
					MEM_free(lines);
					lines=NULL;
					
				}*/
		}
	}
	if(pref_values!=NULL)
	{
		/*for (int i=0;i<pref_cnt;i++)
		{
			cout<<"0-----------------2"<<endl;
			if(pref_values[i]!=NULL)
			{
				cout<<"0-----------------3.1"<<endl;
				MEM_free(pref_values[i]);
				cout<<"0-----------------3.2"<<endl;
				pref_values[i]=NULL;
				cout<<"0-----------------3.3"<<endl;
			}
		}*/
		MEM_free(pref_values);
		pref_values=NULL;
	}
	if(atts!=NULL)
	{
		MEM_free(atts);
		atts=NULL;
	}
	if(rels!=NULL)
	{
		MEM_free(rels);
		rels=NULL;
	}


	try
	{
		conn.Commit();
	}
	catch (SAException e)
	{
		try
		{
			conn.Rollback();
		}
		catch (SAException)
		{
		}
		printf("error:%s\n", e.ErrMessage().GetMultiByteChars());
	}
	conn.Disconnect();
}
int tx_erp_bom(EPM_action_message_t msg)
{
	erp_bom(msg.task);
	return 0;
}

