/** 
* @addtogroup			workflow
* @{
*/

/**
* @file					xy_create_material_code.cpp
*
* @brief				create material code according to some rev master properties
* 
* @author				Ray	Li
*
* @history
* ===================================================================================
* Date					Name				Description
* 27-Jul-2009			Ray				created

*/

/**
* @remarks:			handler usage description
*
* @Handler:			xy-create-material-code 
*
* @Description:		This handler will assign some value to its form property
*
* @Syntax:			xy-create-material-code -type=产品,零组件 -required_props=prop1,prop2,prop3 -sid_leng=3 -target_prop=target_prop_name [-debug=true|false]
* @Arguments:		-type = ItemRevision types, like 产品,零组件
*								specified target ItemRevision will be processed, others skipped, 
*								eg: 产品,零组件
*
*					-target_prop = target property
*								the new prop value assigned to this property
*
*					-target_value = target property
*								the new prop value assigned to this property
*					
*					-debug = true | false
*								When the argument is set to 'true' (case-insensitive), there will be more messages written in the syslog file. The default value is false.
*					
* @Placement:       not specified
* 
* @Restrictions:	none
*
*/

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

/**
* @headerfile			tcua 头文件
*/

#include <tccore/item.h>
#include <tccore/grmtype.h>
#include <tccore/grm.h>
#include <sa/am.h>
#include <tccore/aom.h>
#include <tccore/aom_prop.h>
#include <property/prop_errors.h>
#include <lov/lov_errors.h>
#include <lov/lov.h>
#include <tccore/tctype.h>
#include <res/res_itk.h>

/**
* @headerfile			standard c & cpp header files
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <math.h>

#include <string>
#include <vector>
#include <map>
#include <fstream>
//#include <iostream>
using namespace std;

/**
* @headerfile			user's header files
*/


#include "string_helper.h"
#include "itk_service_common.h"
#include "register_handler_methods.h"
#include "error_handling.h"

static int CycleLovFilter( tag_t lov_tag, const char *prop_value, int lov_order, int filter_level, string &prop_desc )
{
	int ifail = ITK_ok;

	if (lov_tag == NULLTAG)
		return ITK_ok;
	else if ( prop_desc.size()==0 )
	{
		if (filter_level == lov_order)
		{
			int n_values = 0, lov_index = 0;
			char **lov_values = NULL;
			logical find_prop_value = FALSE;

			ITKCALL( LOV_ask_values_string( lov_tag, &n_values, &lov_values ) );
			for (int li=0; li<n_values; li++)
			{
				if (strcmp(lov_values[li], prop_value) == 0)
				{
					lov_index = li;
					find_prop_value = TRUE;
					break;
				}
			}
			MEM_free(lov_values);

			if (find_prop_value)
			{
				LOV_usage_t usage;
				char        **desc_strings = NULL;
				logical     *is_null = NULL;
				logical     *is_empty = NULL;

				ITKCALL( LOV_ask_value_descriptions( lov_tag, &usage,
					&n_values, &desc_strings, &is_null, &is_empty ) );
				if (is_null[lov_index]==FALSE && is_empty[lov_index]==FALSE)
				{
					prop_desc.assign(desc_strings[lov_index]);
				}
				MEM_free(desc_strings);
				MEM_free(is_null);
				MEM_free(is_empty);

				return ITK_ok;
			}
		}		
		else
		{
			int n_listOfFilters = 0, *listOfFiltersIndexes = NULL;
			tag_t *listOfFilters = NULL;

			ITKCALL( LOV_ask_value_filters( lov_tag, &n_listOfFilters, &listOfFiltersIndexes, &listOfFilters ) );
			if (n_listOfFilters>0)
			{
				for (int li=0; li<n_listOfFilters; li++)
				{
					if (prop_desc.size()==0)
					{
						int new_filter_level = filter_level + 1;
						ifail = CycleLovFilter( listOfFilters[li], prop_value, lov_order, new_filter_level, prop_desc );
					}		
					else
						break;
				}
				MEM_free( listOfFiltersIndexes );
				MEM_free( listOfFilters );
			}
		}	
	}

	return ifail;
}


static int FindPropLovDesc( tag_t object, const char *prop_name, PROP_value_type_t prop_type, string &prop_value )
{
	if (object==NULLTAG)
		return POM_inst_not_loaded;

	prop_value.clear();

	//数组属性统一处理
	int max_prop_elems = 0;
	ITKCALL( AOM_ask_max_num_elements( object, prop_name, &max_prop_elems ) );
	if( max_prop_elems != 1 )
	{
		char *d_vlaue = NULL;
		ITKCALL( AOM_UIF_ask_value( object, prop_name, &d_vlaue ) );
		if (d_vlaue && *d_vlaue)
		{
			prop_value.assign(d_vlaue);
			MEM_free(d_vlaue);
			return ITK_ok;
		}
	}
	else
	{
		if (prop_type == PROP_string)
		{
			tag_t prop_descriptor = NULLTAG;
			ITKCALL( AOM_ask_descriptor( object, prop_name, &prop_descriptor ) );

			logical is_lov_des_attached = FALSE;
			ITKCALL( PROPDESC_is_lov_desc_attach( prop_descriptor, &is_lov_des_attached ) );
			if (is_lov_des_attached) //如果当前属性已经是lov的描述，则不再处理，仅赋值给返回对象
			{
				char *str_value = NULL;
				ITKCALL( AOM_ask_value_string( object, prop_name, &str_value ) );
				if (str_value && *str_value)
				{
					prop_value.assign(str_value);
					MEM_free(str_value);
				}
			}
			else
			{
				char *str_value = NULL;
				ITKCALL( AOM_ask_value_string( object, prop_name, &str_value ) );

				if (str_value && *str_value) //仅在属性有值的情况下取其lov描述
				{
					tag_t lov_tag = NULLTAG;
					ITKCALL( AOM_ask_lov( object, prop_name, &lov_tag ) );

					if (lov_tag) //如果没有与属性关联的lov，则不处理
					{
						int lov_order = 0;

						char* object_type = NULL;
						ITKCALL( WSOM_ask_object_type2( object, &object_type ) );
						ITKCALL( LOV_ask_attached_dependency_order( object_type, prop_name, &lov_order ) );

						string prop_desc;
						CycleLovFilter(lov_tag, str_value, lov_order, 1, prop_desc );
						if (prop_desc.size()>0)
							prop_value.assign(prop_desc);
					}

					if (prop_value.size()==0)
					{
						prop_value.assign(str_value);
					}

					MEM_free(str_value);
					return ITK_ok;
				}
			}
		}
		else if (prop_type == PROP_int)
		{
			int int_value = NULL;
			ITKCALL( AOM_ask_value_int( object, prop_name, &int_value ) );
			char buf[100] = "";
			sprintf( buf, "%d", int_value );
			prop_value.assign(buf);
		}
	}

	return ITK_ok;
}




int xy_assign_form_props(EPM_action_message_t msg)
{
	int ifail = ITK_ok;
	logical is_debug = FALSE;
	char buf[BUFSIZ] = "", *flag = NULL, *value = NULL;

	//item master form relation type
	tag_t master_form_rel_type = NULLTAG;
	ITKCALL( GRM_find_relation_type( TC_master_form_rtype, &master_form_rel_type ) );

	//parse some arguments
	map<string,string> item_types_map;
	map<string,string>::iterator item_types_map_iter = item_types_map.begin();
	vector<string>     required_props_vec;
	int sid_leng = 0, max_sid = 0;
	char target_prop[WSO_name_size_c + 1] = "";
	char target_value[WSO_name_size_c + 1] = "";
	int num_of_arguments = TC_number_of_arguments( msg.arguments );
	for (int i=0; i<num_of_arguments; i++)
	{
		ITKCALL( ITK_ask_argument_named_value( TC_next_argument( msg.arguments ), &flag, &value ) );
printf( "value = %s\n", value );
		if ( strcmp( flag, "type" ) == 0 && value != NULL )
		{
			vector<string> ans;
			Split( value, ',', ans );
			for (size_t j=0; j<ans.size(); j++)
			{
				printf("here\n");
				item_types_map.insert(make_pair(ans[j],ans[j]));		
			}
		}
		//else if ( strcmp( flag, "required_props" ) == 0 && value != NULL )
		//{
		//	vector<string> ans;
		//	Split( value, ',', ans ); printf( "ans size = %d\n", ans.size() );
		//	for (size_t j=0; j<ans.size(); j++)
		//	{
		//		required_props_vec.push_back(ans[j]);		
		//	}
		//}
		//else if ( strcmp( flag, "sid_leng" ) == 0 && value != NULL )
		//{
		//	sid_leng = atoi(value); 
		//	max_sid = (int)(pow( 10.0, sid_leng )) - 1;
		//}
		else if ( strcmp( flag, "target_prop" ) == 0 && value != NULL )
		{
			strcpy( target_prop, value );
		} //check debug indicator
		else if ( strcmp( flag, "target_value" ) == 0 && value != NULL )
		{
			strcpy( target_value, value );
		} //check debug indicator
		else if( strcmp( flag, "debug" ) == 0 && value != NULL )
		{
			if( strcmp( value, "true" ) == 0 )
				is_debug = TRUE;
		}

		MEM_free( flag );
		MEM_free( value );
	}

//STEP 1:
	//check handler arguments
	printf("11111111\n");
	if (item_types_map.size()==0)
	{
		printf( ("type argument is not specified, please check!\n") );
		printf("type argument is not specified, please check!\n");
		return EPM_missing_req_arg;
	}
	//else if ( required_props_vec.size()==0)
	//{
	//	LOG_ECHO( ("required_props argument is not specified, please check!\n") );
	//	return EPM_missing_req_arg;
	//}
	//else if ( sid_leng==0 )
	//{
	//	LOG_ECHO( ("sid_leng argument is not valid, please check!\n") );
	//	return EPM_missing_req_arg;
	//}
	else if (strlen(target_prop)==0 )
	{
		printf( ("target_prop argument is not valid, please check!\n") );
		printf("target_prop is not specified, please check!\n");
		return EPM_missing_req_arg;
	}

	//logical prop_not_defined = FALSE;
	//logical lov_has_no_value = FALSE;
	//item_types_map_iter = item_types_map.begin();
	//for (; item_types_map_iter!=item_types_map.end(); item_types_map_iter++)
	//{
	//	tag_t item_type = NULLTAG;
	//	char item_type_class[TCTYPE_class_name_size_c+1] = "";
	//	ITKCALL( TCTYPE_find_type( item_types_map_iter->first.c_str(), NULL, &item_type ) );
	//	ITKCALL( TCTYPE_ask_class_name( item_type, item_type_class ) );
	//	if (strcmp( item_type_class, "Item" ) != 0)
	//	{
	//		sprintf( buf, "type %s not Item or its sub type%s\n", item_types_map_iter->first.c_str() );
	//		LOG_ECHO( (buf) );
	//		break;
	//	}

	//	char *rev_master_type_name = NULL;
	//	ITKCALL( ITEM_ask_rev_master_form_type( item_types_map_iter->first.c_str(), &rev_master_type_name ) );

	//	tag_t rev_master_type = NULLTAG;
	//	ITKCALL( TCTYPE_find_type( rev_master_type_name, NULL, &rev_master_type ) );

	//	for ( int ri=0; ri<(int)required_props_vec.size(); ri++)
	//	{
	//		char one_prop[WSO_name_size_c + 1] = "";
	//		strcpy( one_prop, required_props_vec[ri].c_str() );

	//		tag_t pd_tag = NULLTAG;
	//		ifail = TCTYPE_ask_property_by_name( rev_master_type, one_prop, &pd_tag );
	//		if (ifail != ITK_ok || pd_tag == NULLTAG)
	//		{
	//			sprintf( buf, "property %s not found from type %s\n", one_prop, rev_master_type_name );
	//			LOG_ECHO( (buf) );

	//			prop_not_defined = TRUE;
	//			break;
	//		}
	//	}

	//	if (!prop_not_defined)
	//	{
	//		tag_t pd_tag = NULLTAG;
	//		ifail = TCTYPE_ask_property_by_name( rev_master_type, target_prop, &pd_tag );
	//		if (ifail != ITK_ok || pd_tag == NULLTAG)
	//		{
	//			sprintf( buf, "property %s not found from type %s\n", target_prop, rev_master_type_name );
	//			LOG_ECHO( (buf) );

	//			prop_not_defined = TRUE;
	//			break;
	//		}
	//	}

	//	if (prop_not_defined)
	//	{
	//		break;
	//	}
	//}

	//if (prop_not_defined)
	//{
	//	return PROP_no_properties;
	//}

	//if ( is_debug ) //print arguments specified for handler
	//{
	//	item_types_map_iter = item_types_map.begin();
	//	for (; item_types_map_iter!=item_types_map.end(); item_types_map_iter++)
	//	{
	//		sprintf( buf, "Type: %s, ", item_types_map_iter->first.c_str() );
	//		LOG_ECHO( (buf) );
	//	}
	//	sprintf( buf, "\n" );
	//	LOG_ECHO( (buf) );

	//	for ( int ri=0; ri<(int)required_props_vec.size(); ri++)
	//	{
	//		sprintf( buf, "Prop: %s, ", required_props_vec[ri].c_str() );
	//		LOG_ECHO( (buf) );
	//	}
	//	sprintf( buf, "Prop: %s\n", target_prop );
	//	LOG_ECHO( (buf) );

	//	sprintf( buf, "Max Flow ID Leng: %d\n", max_sid );
	//	LOG_ECHO( (buf) );
	//}

//STEP 2:
	//retrieve item revisions related in reference's list
	tag_t job = NULLTAG, root_task = NULLTAG;
	ITKCALL( EPM_ask_job( msg.task, &job ) );
	ITKCALL( EPM_ask_root_task( job, &root_task ) );

	//current task's reference list
	int reference_count = 0;
	tag_t *reference_list = NULL;
	ITKCALL( EPM_ask_attachments( root_task, EPM_target_attachment, &reference_count, &reference_list ) );
	vector<tag_t> reference_revs_vec;
	for (int ri=0; ri<reference_count; ri++)
	{
		printf("22222222\n");
		tag_t class_id = NULLTAG;
		ITKCALL( POM_class_of_instance( reference_list[ri], &class_id ) );
		if ( class_id != NULLTAG )
		{
			char *class_name = NULL;
			ITKCALL( POM_name_of_class( class_id, &class_name ) );
			//TC8==================
			//if ( class_name && *class_name && strcmp( class_name, "ItemRevision" ) == 0 )
			if ( class_name && *class_name && strstr( class_name, "XY" ) != NULL )
			{
				tag_t item_tag = NULLTAG;
				ITKCALL( ITEM_ask_item_of_rev( reference_list[ri], &item_tag ) );

				char* item_type = NULL;
				ITKCALL( ITEM_ask_type2( item_tag, &item_type ) );

				if (item_types_map.find(item_type)!=item_types_map.end())
				{
					printf("33333333\n");
					reference_revs_vec.push_back(reference_list[ri]);
				}
			}

			MEM_free(class_name);
		}
	}

	if (is_debug)
	{
		sprintf( buf, "Total %d objects will be processed\n", reference_revs_vec.size() );
		printf( (buf) );
	}
	printf("444444444\n");
	//处理所有的版本
	for (int vi=0; vi<(int)reference_revs_vec.size(); vi++)
	{
		tag_t one_rev = reference_revs_vec[vi];

		int form_count = 0;
		tag_t *form_list = NULL, master_form = NULLTAG;
		ITKCALL( GRM_list_secondary_objects_only( one_rev, master_form_rel_type, &form_count, &form_list ) );
		master_form = form_list[0];
		MEM_free(form_list);

		//检查target_prop是否有值
		//printf("55555555\n");
		//logical is_null_empty = FALSE;
		//ITKCALL( AOM_is_null_empty( master_form, target_prop, TRUE, &is_null_empty ) );
		//if (!is_null_empty)
		//{
		//	sprintf( "target prop %s had value already!\n", target_prop );
		//	LOG_ECHO( (buf) );
		//	continue;
		//}
		printf("6666666\n");	
		////检查JyErpNoSyncApp（EPR编码申请）是否为“申请”
		//char *apply_value = NULL;
		//ITKCALL( AOM_ask_value_string( master_form, "JyErpNoSyncApp", &apply_value ) );
		//if ( apply_value && *apply_value && strcmp( apply_value, "不申请" ) == 0 )
		//{
		//	MEM_free(apply_value);
		//	continue;
		//}
		//MEM_free(apply_value);

		map<string,PROP_value_type_t> prop_type_map;
		map<string,PROP_value_type_t>::iterator prop_type_map_iter;
		////得到指定属性的值类型
		//for ( int ri=0; ri<(int)required_props_vec.size(); ri++)
		//{
		//	PROP_value_type_t valtype;
		//	char *valtype_n = NULL;
		//	ITKCALL( AOM_ask_value_type( master_form, required_props_vec[ri].c_str(), &valtype, &valtype_n ) );
		//	if (is_debug)
		//	{
		//		sprintf( buf, "prop type = %s\n", valtype_n );
		//	}
		//	MEM_free(valtype_n);
		//	prop_type_map.insert( make_pair(required_props_vec[ri], valtype) );
		//}

		/*得到指定的属性
		string material_code_mark("");
		for ( int ri=0; ri<(int)required_props_vec.size(); ri++)
		{
			prop_type_map_iter = prop_type_map.find(required_props_vec[ri]);
			PROP_value_type_t valtype = prop_type_map_iter->second;

			string prop_value;
			FindPropLovDesc( master_form, required_props_vec[ri].c_str(), valtype, prop_value );
			if (prop_value.size()>0)
			{
				material_code_mark.append(prop_value);
			}
		}

		char *newID = NULL;
		ITKCALL( SERVICE_internal_part_no( material_code_mark.c_str(), sid_leng, 1, max_sid, 1, &newID ) );
		if (newID && *newID && strlen(newID)>0)
		{
			material_code_mark.assign(newID);
			MEM_free(newID);
		}

		if (is_debug)
		{
			sprintf( buf, "new material code is %s\n", material_code_mark.c_str() );
			LOG_ECHO( (buf) );
		}*/

		//检查写权限
		printf("7777777\n");
		logical can_change_form = FALSE;
		ITKCALL( AM_check_privilege( master_form, "WRITE", &can_change_form ) );
		if (can_change_form)
		{
			//PROP_value_type_t valtype;
			//char *valtype_n = NULL;
			//ITKCALL( AOM_ask_value_type( master_form, target_prop, &valtype, &valtype_n ) );
			//if (is_debug)
			//{
			//	sprintf( buf, "prop type = %s\n", valtype_n );
			//}
			//MEM_free(valtype_n);
			//if (valtype == PROP_string)
			//{
			//	tag_t prop_descriptor = NULLTAG;
			//	ITKCALL( AOM_ask_descriptor( object, prop_name, &prop_descriptor ) );

			//	logical is_lov_des_attached = FALSE;
			//	ITKCALL( PROPDESC_is_lov_desc_attach( prop_descriptor, &is_lov_des_attached ) );
			//	if (is_lov_des_attached) //如果当前属性已经是lov的描述，则不再处理，仅赋值给返回对象
			//	{
			//		//char *str_value = NULL;
			//		//ITKCALL( AOM_ask_value_string( object, prop_name, &str_value ) );
			//		//if (str_value && *str_value)
			//		//{
			//		//	prop_value.assign(str_value);
			//		//	MEM_free(str_value);
			//		//}
			//	}				
			//}
			//TC8=============
			//ITKCALL( AOM_lock( master_form ) );
			
			//ITKCALL( AOM_set_value_string( master_form, target_prop, material_code_mark.c_str() ) );
			ITKCALL(RES_checkout2(master_form,"","","",RES_EXCLUSIVE_RESERVE));
			ITKCALL(RES_cancel_checkout (master_form,false));
			ITKCALL( AOM_set_value_string( master_form, target_prop, target_value ) );
			ITKCALL( AOM_save( master_form ) );
			ITKCALL( AOM_unlock( master_form ) );
		}
		else
		{
			printf( ("reviewer has no write privilege to add attachment\n" ) );
			return AM_insufficient_access;
		}
	}

	return ITK_ok;
}

