#pragma warning (disable: 4996) 
#pragma warning (disable: 4819) 
#pragma warning (disable: 4995) 

#include <tc/tc.h>
#include "epm_handler_common.h"

#include <ict/ict_userservice.h>
#include <tccore/custom.h>
#include <epm/epm_toolkit_tc_utils.h>
#include <tccore/aom.h>
#include <tccore/aom_prop.h>
#include <tccore/item.h>
#include <bom/bom.h>
#include "ps/ps.h";
#include "ps/vrule.h"
#include "sstream"
#include <tccore/grm.h>
#include "epm/epm.h"
#include "sa/sa.h"
#include "libxl.h"
#include <map>
#include "epm/signoff.h"
#include <ctime>
#include <vector>
#include <locale>
#include <codecvt>
#include "ae/dataset.h"
#include <iostream>
#include <stdlib.h>
#include <tccore/aom.h>
#include <tc/emh.h>
#include <ict/ict_userservice.h>
#include <tc/tc.h>
#include <tccore/tctype.h>
#include <sa/tcfile.h>
#include <ss/ss_errors.h>
#include <string.h>
#include <time.h>
#include <tccore/project.h>

#include "tchar.h"
#include <ics/ics.h>
#include "tc_log.h"
#include <tc/preferences.h>
#include "erp_utils.h"
using namespace libxl;
extern "C" int POM_AM__set_application_bypass(logical bypass);
string ws2s(const std::wstring& wstr)
{
	
	if (wstr.empty()||wstr.length()==0) return std::string();
	int size_needed = WideCharToMultiByte(CP_ACP, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
	std::string strTo(size_needed, 0);
	WideCharToMultiByte(CP_ACP, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
	return strTo;
}

 static wstring Str2Wstr (string str )
{
    if (str.length() == 0)
        return L"";

    std::wstring wstr;
    wstr.assign (str.begin(), str.end());
    return wstr;
}
// 把char *转换为TCHAR *或WCHAR *
TCHAR convertTemp1[256] = {0};
TCHAR convertTemp2[256] = {0};
bool convertBufferSwitch(false);
TCHAR* CharToTchar(const char* str, int len)
{
	#ifdef _UNICODE 
	TCHAR* temp = convertBufferSwitch ? convertTemp1 : convertTemp2; 
	convertBufferSwitch = !convertBufferSwitch; 
	memset(temp, 0, sizeof(convertTemp1)); 
	MultiByteToWideChar(CP_UTF8, 0, str, len, temp, 256); 
	return temp;
	#else 
	return str;
	#endif
}
/*将char转换成tchar,旨在解决中文乱码的问题，可是转换出来的第一个都是乱码，不管是不是中文*/
TCHAR* chineseChar(const char* sText)
{
	//计算char *数组大小，以字节为单位，一个汉字占两个字节
    int charLen = strlen(sText);
    //计算多字节字符的大小，按字符计算。
    int len = MultiByteToWideChar(CP_ACP,0,sText,charLen,NULL,0);
    //为宽字节字符数组申请空间，数组大小为按字节计算的多字节字符大小
    TCHAR *buf = new TCHAR[len + 1];
    //多字节编码转换成宽字节编码
//    MultiByteToWideChar(CP_ACP,0,sText,charLen,buf,len);
    MultiByteToWideChar(CP_ACP,0,sText,-1,buf,len+1);
//    buf[len] = '\0'; //添加字符串结尾，注意不是len+1
	 buf[len+1] = '\0'; 
   buf[0]='\0'; 
    //删除缓冲区
    delete []buf;
	return buf;
}

TCHAR* chineseChar2(const char* sText)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, sText, -1, NULL, 0);
	TCHAR *buf = (TCHAR *)malloc(len);
	MultiByteToWideChar(CP_UTF8, 0, sText, -1, buf, len);
	//删除缓冲区
//    delete []buf;
	return buf;
}

 void get_current_date_and_time(char *date_time)
{
    time_t the_time;
    struct tm *time_ptr;
    char *time_format = "%Y%m%d-%H%M%S";

    the_time = time((time_t *)0);
    time_ptr = localtime (&the_time);
    strftime(date_time, 128, time_format, time_ptr);
}

typedef struct{
	string ITEM_ID_VIRTUAL;//虚拟件id号
	string VIRTUAL_SPEC;//虚拟件的规格型号
	string VIRTUAL_TECH;//虚拟件的技术型号
	string ITEM_ID_ACTUAL;//实体件id号
	string ACTUAL_SPEC;//实体件规格型号
//	string ACTUAL_TECH;//实体件技术型号
}PROPERTY_STRUCT;
//判断虚拟件类型的物料，把虚拟件下的实体的最新版本信息写入到一张配置表中，配置表中的版本信息仅是最新的
int jk_add_actual(EPM_action_message_t msg)
{
	cout<<"把虚拟和实体件的对象关系写到表格里"<<endl;
	EPM_decision_t decision = EPM_go;
	int ifail = ITK_ok, arg_cnt = 0, i = 0, att_cnt = 0;
	tag_t task_tag = NULLTAG, rootTask_tag = NULLTAG, *attachments = NULL;
	vector<PROPERTY_STRUCT> vec;
	char * object_TYPE_1 = NULL;
	char * object_string1=NULL;
	string value_type = "";
	string value_property="";
	char * ref_type=NULL;
	int actualNum=0;
	tag_t *actualtags=NULL;
	string errorMessage="";
	//获取当前触发的任务
	task_tag = msg.task;
	//获取根流程节点
	ifail = EPM_ask_root_task(task_tag, &rootTask_tag);
	//获取目标引用对象
	ifail = EPM_ask_attachments(rootTask_tag, EPM_target_attachment, &att_cnt, &attachments);
	int reference_count=0;tag_t * reference_attachment=NULLTAG;
	ifail = EPM_ask_attachments(rootTask_tag, EPM_reference_attachment, &reference_count, &reference_attachment);
	/*tag_t classObj,attribute_tag;
	ICS_ask_classification_object(task_tag,&classObj);
	ITKCALL(ifail=ICS_ask_attribute(classObj,"产品识别号",&attribute_tag));
	char *classValue=NULL;
	if(ifail==0)
	{
		ICS_ask_attribute_value(classObj,"产品识别号",&classValue);
	}*/
	
	

	boolean warn=false;
	boolean ctn=false;
	//循环目标对象
	//获得最新发布版本的实体对象版本的技术规格和id
	for (i = 0; i < att_cnt; i++) {
		ifail = AOM_ask_value_string(attachments[i], "object_type", &object_TYPE_1);//对象类型
		cout << object_TYPE_1;
		cout << endl;
		ctn=false;
		if(strcmp("JK8VirtlMaterialRevision",object_TYPE_1)==0)//如果是虚拟件版本类型，就检查其下的实体物料的关系下有没有实体物料对象，并且对象下有发布的版本
		{
			int formCount=0;
			tag_t * formTags=NULLTAG;
			AOM_ask_value_tags(attachments[i],"IMAN_master_form_rev",&formCount,&formTags);
			char *virtualTechValue=NULL;
			char *virtualSpecValue=NULL;
			AOM_ask_value_string(formTags[0],"jk8SpecModel",&virtualSpecValue);
			AOM_ask_value_string(formTags[0],"jk8TechModel",&virtualTechValue);

			cout<<"7----------------"<<endl;
			ifail=AOM_ask_value_tags(attachments[i],"JK8InstanceMaterialRelation",&actualNum,&actualtags);
			for (int j=0;j<actualNum;j++)
			{
				
				char * object_TYPE_2 = NULL;
				AOM_ask_value_string(actualtags[j],"object_type",&object_TYPE_2);
				//如果关系下的对象类型符合，查看下面有没有最新发布的版本
				if(strcmp(object_TYPE_2,"JK8Material")==0)
				{
					cout<<"8----------------------"<<endl;
					//revision_list获得所有版本
					int revisionNums=0;
					tag_t *revisionTags=NULLTAG;
					ITKCALL(ifail=AOM_ask_value_tags(actualtags[j],"revision_list",&revisionNums,&revisionTags));
					string actualID="";
					string actualTech="";
					string virtualID ="";
					for (int k=0;k<revisionNums;k++)
					{
						int releaseNums=0;
						tag_t * releaseTags=NULLTAG;
						ITKCALL(ifail=AOM_ask_value_tags(revisionTags[k],"release_status_list",&releaseNums,&releaseTags));
						cout<<"10----------------------------------"<<endl;
						if(releaseNums>0)
						{
								cout<<"11----------------------------------"<<endl;
							for (int n=0;n<releaseNums;n++)
							{
									cout<<"12----------------------------------"<<endl;
								char *value=NULL;//IMAN_master_form_rev
								int revNums=0;
								tag_t *rm=NULLTAG;
								ITKCALL(ifail=AOM_ask_value_string(revisionTags[k],"item_id",&value));//id
								actualID=value;
								ITKCALL(ifail=AOM_ask_value_tags(revisionTags[k],"IMAN_master_form_rev",&revNums,&rm));
								ITKCALL(ifail=AOM_ask_value_string(rm[0],"jk8SpecModel",&value));//规格型号
								actualTech=value;
								

								ITKCALL(ifail = AOM_ask_value_string(attachments[i], "item_id", &value));//对象类型
								virtualID=value;
								if(value!=NULL)
								{
									MEM_free(value);
									value=NULL;
								}
									cout<<"13----------------------------------"<<endl;
								if(rm!=NULL)
								{
									MEM_free(rm);
									rm=NULL;
								}
									cout<<"14----------------------------------"<<endl;
							}
							PROPERTY_STRUCT one_elem;
							one_elem.VIRTUAL_SPEC=virtualSpecValue;
							one_elem.VIRTUAL_TECH=virtualTechValue;
							one_elem.ITEM_ID_ACTUAL=actualID;
							one_elem.ITEM_ID_VIRTUAL=virtualID;
							one_elem.ACTUAL_SPEC=actualTech;
							vec.push_back(one_elem);

						}
						
						if(releaseTags!=NULL)
						{
							MEM_free(releaseTags);
							releaseTags=NULL;
						}
							cout<<"15----------------------------------"<<endl;
						if(releaseNums>0)
						{
							
							ctn=true;
							break;
						}
							cout<<"16----------------------------------"<<endl;
					}
					cout<<"9----------------------"<<endl;
				
					if(revisionTags!=NULL)
					{
						MEM_free(revisionTags);
						revisionTags=NULL;
					}

				}
				if(object_TYPE_2!=NULL)
				{
					MEM_free(object_TYPE_2);
					object_TYPE_2=NULL;
				}	
			}
			
			if(virtualTechValue!=NULL)
			{
				MEM_free(virtualTechValue);
				virtualTechValue=NULL;
			}
			if(virtualSpecValue!=NULL)
			{
				MEM_free(virtualSpecValue);
				virtualSpecValue=NULL;
			}
			if(actualtags!=NULL)
			{
				MEM_free(actualtags);
				actualtags=NULL;
			}
			if(formTags!=NULL)
			{
				MEM_free(formTags);
				formTags=NULL;
			}

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

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

	cout<<"开始读取excel"<<endl;
	//先读取表格所有的id，写入到vec中
	vector<PROPERTY_STRUCT> vec2;
	
	tag_t excelTag;
	vector<string> pref_vec;
	getPrefStrings("JK_VIRTUAL_PUID",TC_preference_site, pref_vec);//测试：T1exiQYYYvbLjA  正式：
	if(pref_vec.size() > 0){
		ITK__convert_uid_to_tag(pref_vec[0].c_str(),&excelTag);
		if(excelTag == NULLTAG){
			WriteLog_jk("PUID[%s]不能转换成对象\n",pref_vec[0].c_str());
			CloseLog_jk();
			printf("PUID[%s]不能转换成对象\n",pref_vec[0].c_str());
		
		}
	}


//	ITK__convert_uid_to_tag("T1exiQYYYvbLjA",&excelTag);
	Book* book = nullptr;
	book = xlCreateBook();//xls文件用xlCreateBook() 函数打开，xlsx文件是xml结构，所以得用xlCreateXMLBook() 函数来打开。
	book->setKey(L"Halil Kural", L"windows-2723210a07c4e90162b26966a8jcdboe");//如果购买了该库，则设置相应的key，若没有购买，则不用这行
	int n_refs = 0;
	tag_t* refs = NULL;

	ifail = AE_ask_all_dataset_named_refs(excelTag, "excel", &n_refs, &refs);
	if (ifail != ITK_ok) { /* your error logic here */ }

	char current_date_time_str[128 + 1] = {"\0"};
	get_current_date_and_time(current_date_time_str);
	string time_now=current_date_time_str;
	time_now="E:\\TEMP\\"+time_now+".xls";
	cout<<"文件路径----------"<<time_now;

	ifail = AE_export_named_ref(excelTag, "excel", time_now.c_str());
	if (ifail != ITK_ok) { /* your error logic here */ }
	//检查是否存在单元格名称为“xxxx”
	wstringstream excel_path;
	
//	excel_path<<"C:\\TEMP\\export_text.xls";
	excel_path<<time_now.c_str();
	Sheet* sheet;
	if (book->load(excel_path.str().c_str()))
	{
		cout<<"88888888"<<endl;
		 sheet = book->getSheet(0);//获得第1个sheet页
		int lastRow=sheet->lastRow();
		for(int i=1;i<lastRow;i++)
		{
		
		
			string value0=ws2s(sheet->readStr(i, 0));//虚拟件id
			string value1=ws2s(sheet->readStr(i, 1));//虚拟件技术型号
			string value2=ws2s(sheet->readStr(i, 2));//虚拟件规格型号
			string value3=ws2s(sheet->readStr(i, 3));//实体件规格型号
			string value4=ws2s(sheet->readStr(i, 4));//实体物料ID
			cout<<value0<<endl;
			cout<<value1<<endl;
			cout<<value2<<endl;
			cout<<value3<<endl;
			cout<<value4<<endl;
			if(value0.length()>0||value1.length()>0||value2.length()>0||value3.length()>0||value4.length()>0)
			{
				PROPERTY_STRUCT one_elem2;
				
				
				one_elem2.ITEM_ID_VIRTUAL=value0;
				one_elem2.VIRTUAL_SPEC=value1;
				one_elem2.VIRTUAL_TECH=value2;
				one_elem2.ACTUAL_SPEC=value3;
				one_elem2.ITEM_ID_ACTUAL=value4;
				vec2.push_back(one_elem2);

			}

		}



	}
	cout<<"1-----------------------"<<endl;
	cout<<"vec.size()-----------------------"<<vec.size()<<endl;
	cout<<"vec2.size()-----------------------"<<vec2.size()<<endl;
	//遍历vector，写入到表格中
	vector<PROPERTY_STRUCT> vec3;
	if(vec2.size()>0)
	{
		for (int i=0;i<vec2.size();i++)
		{
			string vec2VirtulID=vec2[i].ITEM_ID_VIRTUAL;//旧配置表中的数据
			cout<<"旧虚拟件ID："<<vec2VirtulID<<"----------"<<endl;
			for(int j=0;j<vec.size();j++)
			{
				string vec1VirtulID=vec[j].ITEM_ID_VIRTUAL;
				cout<<"新虚拟件ID："<<vec1VirtulID<<"----------"<<endl;
				if(strcmp(vec2VirtulID.c_str(),vec1VirtulID.c_str())==0)
				{
					cout<<"bingo"<<endl;
					break;
				}else
				{
					vec3.push_back(vec2[i]);
					break;
				}
			}

		}
	}else
	{
		
	}
	
	cout<<"2-----------------------"<<endl;
	for(int j=0;j<vec.size();j++)
	{
		vec3.push_back(vec[j]);
	}
	cout<<"3-----------------------"<<endl;
	//写到表格中
	TCHAR *array1;
	TCHAR array2[100];
	for (int i=0;i<vec3.size();i++)
	{
		//虚拟物料ID
		 array1 = CharToTchar(vec3[i].ITEM_ID_VIRTUAL.c_str(),200);
		sheet->writeStr(i+1, 0, array1);
		
		//虚拟物料技术型号
		 MultiByteToWideChar(CP_ACP, 0, vec3[i].VIRTUAL_TECH.c_str(), -1, array2, 100);
		sheet->writeStr(i+1, 1,array2 );

		//虚拟物料规格型号
		 MultiByteToWideChar(CP_ACP, 0, vec3[i].VIRTUAL_SPEC.c_str(), -1, array2, 100);
		sheet->writeStr(i+1, 2,array2 );

		//实体物料规格型号
		 MultiByteToWideChar(CP_ACP, 0, vec3[i].ACTUAL_SPEC.c_str(), -1, array2, 100);
		sheet->writeStr(i+1, 3,array2 );

		 array1 = CharToTchar(vec3[i].ITEM_ID_ACTUAL.c_str(),200);
		sheet->writeStr(i+1, 4, array1);
	}

//	if (book->save(L"C:\\TEMP\\export_text.xls"))//保存到example.xls
	if (book->save(excel_path.str().c_str()))//保存到example.xls
        {
            //.....
        }
        else
        {
            std::cout << book->errorMessage() << std::endl;
        }
        book->release();//释放对象！！！！
	//TODO 替换数据集,开旁路
		POM_AM__set_application_bypass(true);
		tag_t spec_dataset_rev = NULLTAG,
			ref_object = NULLTAG;
		AE_reference_type_t reference_type;
		ITKCALL(AE_ask_dataset_latest_rev(excelTag, &spec_dataset_rev));
		char ref_name[WSO_name_size_c + 1] = "excel";
		ITKCALL(AE_ask_dataset_named_ref(spec_dataset_rev, ref_name, &reference_type, &ref_object));
		if(reference_type == AE_PART_OF)
		{
			char pathname[SS_MAXPATHLEN] = "";
			ITKCALL(IMF_ask_file_pathname(ref_object, SS_WNT_MACHINE, pathname));
			char origin_file_name[IMF_filename_size_c + 1] = "";
			ITKCALL(IMF_ask_original_file_name(ref_object, origin_file_name));

			tag_t new_file_tag = NULLTAG;
			IMF_file_t file_descriptor;	
			ITKCALL(IMF_import_file(time_now.c_str(), NULL, SS_BINARY, &new_file_tag, &file_descriptor));
			ITKCALL(IMF_set_original_file_name(new_file_tag, origin_file_name));
			ITKCALL(IMF_close_file(file_descriptor));
			ITKCALL(AOM_save(new_file_tag));
			ITKCALL(AOM_unlock(new_file_tag));
			ITKCALL(AOM_lock(spec_dataset_rev));
			ITKCALL(AE_remove_dataset_named_ref_by_tag(spec_dataset_rev, "excel", ref_object));
			ITKCALL(AE_add_dataset_named_ref(spec_dataset_rev, "excel", AE_PART_OF, new_file_tag));
			ITKCALL(AOM_save(spec_dataset_rev));
			ITKCALL(AOM_unlock(spec_dataset_rev));
		}
		POM_AM__set_application_bypass(false);

	return 0;
}