/**
* @addtogroup			service
* @{
*/

/**
* @file					service_part_no.cpp
* @brief				retrieve new item id according some mark code
* @date					2009/7/26
* @author				James Pang
* @history
* ===================================================================================
* Date					Name				Description
* 26-Jul-2009			James				created
*/
#pragma warning(disable:4819)
#pragma warning(disable:4267)

/**
* @headerfile			tcua 头文件
*/
#include <ict/ict_userservice.h>
#include <ae/dataset.h>
#include <ae/datasettype.h>
#include <tccore/grmtype.h>
#include <tccore/grm.h>
#include <tccore/item.h>
#include <tccore/aom.h>
#include <tc/folder.h>
#include <sa/user.h>
#include <pom/enq/enq.h>

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

/**
* @headerfile			user's header files
*/
#include "itk_service_common.h"
#include "error_handling.h"


#define CONSOLE_PRINT 1

/* Define the number of retries when fetching the next ID. */
/* This must be stored in both numeric and string forms.   */

#define GET_ID_RETRIES  10
#define CYCLE_TIMES   10
#define STARTNUMBER  1
#define PADNUMBER  4
#define RETRY_STRING   "10"
#define HANDLE_ERROR_S1(E,S) \
{ EMH_store_initial_error_s1(EMH_severity_error,(E),(S)); return(E); }

#define REPORT_IFAIL(M) \
	ifail?printf("%s : ERROR : ifail = %d\n",M,ifail):printf("%s : Ok\n",M)

#define HANDLE_ERROR(E) \
{ EMH_store_initial_error(EMH_severity_error,(E)); return(E); }

#define HANDLE_ERROR_S1(E,S) \
{ EMH_store_initial_error_s1(EMH_severity_error,(E),(S)); return(E); }

#define HANDLE_ERROR_AND_RELEASE(E,I) \
{ \
	(void)release_number(I); \
	EMH_store_initial_error(EMH_severity_error,(E)); \
	return(E); \
}

#define TEST_ERROR(E) \
	if ((E) != ITK_ok) return(E);

#define TEST_POM_ERROR(E) \
	if ((E) != ITK_ok) HANDLE_ERROR(E)

#define TEST_ERROR_AND_RELEASE(E,I) \
	if ((E) != ITK_ok) { (void)release_number(I); return(E); }

/* Define the number of retries when fetching the next ID. */
/* This must be stored in both numeric and string forms.   */
#define GET_ID_RETRIES  10
#define RETRY_STRING   "10"

/* Empty string test macro */
#define IS_EMPTY(S)  (!(*(S)))

/* Define the methods by which a new item name can be obtained */
#define SEED_METHOD   0
#define BUILD_METHOD  1

/* The following define the maximum index number to be used.  *
* Note that the actual maximum is one less than MAXNUM.      *
* NUMERIC_LIMIT must be large enough to store decimal string *
* version of MAXNUM plus a NULL terminator.  */
#define NUMERIC_LIMIT   12
#define MAXNUM          0x7FFFFFFF
/* define the class for which id and rev is generated */
#define CLASS_IS_ITEM       0
#define CLASS_IS_DATASET    1
/* Store the tags for the next_id POM object and the actual ID attribute.  */
/* This saves us having to obtain these every time a user hits the Assign  */
/* button. The logical variables define whether the tags are legal or not. */
/* I tried to set to tag_t's to NULLTAG for this purpose, but the HP C     */
/* compiler did not like this. Typical.                                    */
static logical inst_ok = false;
static logical attr_ok = false;
static tag_t   instance;
static tag_t   attr_id;
static logical is_new = false;
/*Store the class identifier for the id and rev generation. */
/* This helps us share some of the existing codes           */
static int    class_is = -1;

/* Store all Item IDs issued, whether they are used or not.*/
static int    item_ids_issued = 0;
static char** item_ids_issued_list = NULL;
static char*  ITEM_POM_CLASS = "ITEM";

/*------------------------------------------------------------------------------------------------------------------------------*/

/*
*
*   int release_number ( tag_t instance )
*
*   Release the lock on the index number in the database. This is only
*   CALLed in error situations.
*
*   Parameters:
*      instance   The tag of the POM object to be released. This is
*                 returned by the load function.
*
*/
static int release_number ( tag_t instance )
{
	if (instance != NULLTAG)
	{
		return POM_refresh_instances_any_class(1, &instance, POM_no_lock);
	}
	else
	{
		return ITK_ok;
	}
} /* end release_number */


static int ORIGIN_select_counter ( const char *counter_name,int num )
{
	int      i, n;
	tag_t    class_id;
	tag_t    name_attr,num_attr;
	tag_t   *inst_tag;
	char    *value;
	int     num_value;
	logical  vNull, vEmpty;
	int      ifail;

	instance = NULLTAG;
	attr_id  = NULLTAG;
	inst_ok  = false;
	attr_ok  = false;

	/* Find the Next ID class */
	POM_class_id_of_class("ImanNextId", &class_id);


		/* Find all the instances of this class */
	ITKCALL(ifail = POM_instances_of_class(class_id, false, &n, &inst_tag))


		/* Locate the appropriate attribute */
		ITKCALL(ifail = POM_attr_id_of_attr("name","ImanNextId", &name_attr))
		ITKCALL(ifail = POM_attr_id_of_attr ("next_id","ImanNextId",&num_attr))

		/* Try to locate the named instance */
		for (i=0; ((i<n)&&(instance==NULLTAG)); i++)
		{
			ITKCALL(ifail = POM_refresh_instances_any_class(1, &(inst_tag[i]), POM_no_lock))
				ITKCALL(ifail = POM_ask_attr_string(inst_tag[i], name_attr, &value,&vNull, &vEmpty))

				if ((ifail == ITK_ok) &&
					(!vNull)          &&
					(!vEmpty)         &&
					(strcmp(value, counter_name) == 0))
				{
					instance = inst_tag[i];
					ITKCALL(ifail = POM_ask_attr_int (inst_tag[i],num_attr,&num_value,&vNull,&vEmpty))
						printf("num_value=%d\n",num_value);
					ITKCALL(ifail = POM_attr_id_of_attr("next_id","ImanNextId", &num_attr))
						printf("num_attr=%d\n",num_attr);
					printf("inst_tag[i]=%d\n",inst_tag[i]);
					is_new = false;
				}
		}

		//如果没有查到计数器,则创建一个计数器
		if( instance == NULLTAG )
		{
			ITKCALL(ifail = POM_class_id_of_class("ImanNextId", &class_id))
				if (ifail != ITK_ok)
					return ifail;

			ITKCALL(ifail = POM_attr_id_of_attr("name", "ImanNextId", &attr_id))
				if (ifail != ITK_ok)
					return ifail;
			ITKCALL(ifail = POM_attr_id_of_attr("next_id","ImanNextId", &num_attr))
				if (ifail != ITK_ok)
					return ifail;
			ITKCALL(ifail = POM_create_instance(class_id, &instance))
				if (ifail != ITK_ok)
					return ifail;

			ITKCALL(ifail = POM_set_attr_string(1, &instance, attr_id, counter_name))
				if (ifail != ITK_ok)
					return ifail;
			ITKCALL(ifail = POM_set_attr_int (1,&instance,num_attr,num))
				if (ifail != ITK_ok)
					return ifail;
			ITKCALL(ifail = POM_save_instances(1, &instance, true))

				ITKCALL(ifail = POM_refresh_instances_any_class(1, &instance, POM_no_lock))
				printf( "No instance, create one\n" );
			is_new = true;
		}

		inst_ok = true;
		return(ITK_ok);
}


static int get_next_id_attribute(void)
{
	int ifail;
	attr_id = NULLTAG;
	attr_ok = false;
	ITKCALL(ifail = POM_attr_id_of_attr("next_id","ImanNextId", &attr_id))
		TEST_POM_ERROR(ifail)
		attr_ok = true;
	return(ITK_ok);
}


static int load_current_number (const char *counter_name ,  int *num )
{
	int     i;
	logical vNull, vEmpty;
	int     ifail;
	int     temp;
	logical tagValid = false ;

	*num = 0;

	POM_is_tag_valid( instance , &tagValid);
	if (!inst_ok || !tagValid )
	{
		ifail = ORIGIN_select_counter(counter_name, 1);
		TEST_ERROR(ifail)
	}

	/* Try to load and lock the instance */
	ifail = ITK_ok+1;
	for (i=0; ((i<GET_ID_RETRIES) && (ifail!=ITK_ok)); i++)
		ifail = POM_refresh_instances_any_class(1, &instance, POM_modify_lock);
	if (i == GET_ID_RETRIES)
	{
		//if (class_is==CLASS_IS_ITEM)
		//   HANDLE_ERROR_S1(ITEM_next_id_lock_failed,RETRY_STRING)
		//else if (class_is==CLASS_IS_DATASET)
		//   HANDLE_ERROR_S1(AE_next_id_lock_failed,RETRY_STRING)
	}
	TEST_POM_ERROR(ifail)

	if (!attr_ok)
	{
		ifail = get_next_id_attribute();
		TEST_ERROR(ifail)
	}

	ifail = POM_ask_attr_int(instance, attr_id, &temp, &vNull, &vEmpty);
	TEST_POM_ERROR(ifail)
		*num = temp;

	return(ITK_ok);
} /* end load_number */


static int generation_num(char *TeZhengMa,int num_len,int curr_num,char **final_num)
{
	int i=0;
	char pad_string[64],str_num[64];
	char *new_name=NULL;
	if(num_len<0 || num_len>50)
		return -1;
	if(TeZhengMa==NULL)
		return -1;
	strcpy(pad_string,"\0");
	sprintf(str_num,"%d",curr_num);
	printf("str_num = %s\n",str_num);
	printf("strlen = %d\n",strlen(str_num));
	//new_name = (char*)malloc(sizeof(char)*100);
	//strcpy(new_name,"");
	if((num_len-(int)strlen(str_num))>0)
	{
		printf("111\n");
		pad_string[num_len-strlen(str_num)] = '\0';
		for(i=0;i<num_len-strlen(str_num);i++)
		{
			pad_string[i] = '0';
		}
		//pad_string[i+1]='\0';
		*final_num = (char *)MEM_alloc(sizeof(char)*100);

		//strcpy(*final_num,"");
		sprintf(*final_num, "%s%s%s", TeZhengMa, pad_string,str_num);
		//sprintf(new_name, "%s%s%s", TeZhengMa, pad_string,str_num);
		//*final_num = new_name;
		printf("final_num1 = %s\n",*final_num);
	}
	else 
	{
		printf("222\n");
		*final_num = (char *)MEM_alloc(sizeof(char)*100);

		sprintf(*final_num, "%s%s", TeZhengMa, str_num);
		//sprintf(new_name, "%s%s", TeZhengMa, str_num);
		printf("*final_num = %s\n",*final_num);
		//*final_num = new_name;
		//return -1;
	}
	return 0;
}



static int EnqLikeNo(char* TeZhengManWithNumber,int* num)
{
	int ifail;
	int n_instance,n_failtures;
	tag_t 
		enquiry_id = NULLTAG,
		class_to_load_as   = NULLTAG,
		*instances,
		*failed_instances;
	char *enquiryLikeItem = "Select_ITEM";
	char *select_attrs[1] = { "puid" };
	int rows, cols, i, j;
	void ***report = NULL;
	//===============select puid form Item where ITEM_ID like TeZhengManWithNumber%
	printf("creat select\n");
	ITKCALL( POM_enquiry_create(  enquiryLikeItem ) );
	printf("search:%s\n",TeZhengManWithNumber);
	ITKCALL( POM_enquiry_add_select_attrs( enquiryLikeItem, ITEM_POM_CLASS, 1, (const char**) select_attrs ) );
	//"PartIdRev","PmiName",
	ITKCALL( POM_enquiry_set_string_value( enquiryLikeItem, "item_id_value", 1, (const char**)( &TeZhengManWithNumber ), POM_enquiry_asc_order ) );
	//ITKCALL( POM_enquiry_set_string_value( enquiryLikeItem, "item_id_value", 1,"myTeZhengMa1014%", POM_enquiry_bind_value ) );
	ITKCALL( POM_enquiry_set_attr_expr( enquiryLikeItem, "item_id_exp", ITEM_POM_CLASS, "ITEM_ID",  POM_enquiry_like, "item_id_value" ) );

	//ITKCALL( POM_enquiry_set_string_value( enquiryLikeItem, "pmi_id_value", 1, (const char**)( &szPmiId ), POM_enquiry_bind_value ) );
	//ITKCALL( POM_enquiry_set_attr_expr( enquiryLikeItem, "pmi_id_exp", ITEM_POM_CLASS, "PmiId", POM_enquiry_equal, "pmi_id_value" ) );

	//ITKCALL( POM_enquiry_set_expr( enquiryLikeItem, "filter_exp", "item_id_exp", POM_enquiry_and, "pmi_id_exp" ) );
	ITKCALL( POM_enquiry_set_where_expr( enquiryLikeItem, "item_id_exp" ) );

	printf("execute select\n");
	ITKCALL( POM_enquiry_execute( enquiryLikeItem, &rows, &cols, &report ) );
	printf("executed select\n");
	*num= rows;
	/*	for( i=0; i<rows; i++ )
	{
	for( j=0; j<cols; j++ )
	{
	MEM_free( report[i][j] );
	}
	MEM_free( report[i] );
	}
	MEM_free( report );*/
	MEM_free( report );
	//ITKCALL( POM_load_instances_possible_by_enquiry( enquiryLikeItem, ITEM_POM_CLASS, &n_instance, &instances, &n_failtures, &failed_instances ) );
	ITKCALL( ifail = POM_enquiry_delete( enquiryLikeItem ) );
	printf("ifail=%d\n",ifail);
	printf("rows=%d\n",rows);

	return ifail;
}

int SaveCounter(char* TeZhengMa, int length, int start_num, int end_num,int step,char **sNum)
{
	int ifail;
	logical tagValid = false ;
	int number,rows,i=0;
	int *rtn;
	char   *new_num=NULL;
	char	counter_name[255];
	void *returnValueType;

	POM_is_tag_valid( instance , &tagValid);

	ifail = ORIGIN_select_counter(TeZhengMa,start_num);
	TEST_ERROR(ifail)	

		ifail = load_current_number(TeZhengMa,&number);
	printf("counter number = %d\n",number);
	if (!attr_ok)
	{
		ifail = get_next_id_attribute();
		TEST_ERROR(ifail)
	}
	//sprintf(item_number,"%s%d",TeZhengMa,number+1);
	*sNum = (char *)MEM_alloc(sizeof(char)*100);
	/* for( i=1;i<CYCLE_TIMES;i++)                    //zjd
	*/
	i=0;
	do
	{

		i++;
		ifail = generation_num(TeZhengMa,length,number+i,&new_num);	
		sprintf(*sNum,"%s",new_num);
		printf("new_num = %s\n",new_num);
		strcpy(counter_name,"%");
		strcat(counter_name,new_num);
		strcat(counter_name,"%");
		printf("new_num of TeZhengMa=%s\n",counter_name);

		ifail = EnqLikeNo(counter_name,&rows);
		//if(new_num!=NULL)
		//	MEM_free(new_num);		
		/* if(rows==0)                           //zjd
		{
		break;
		}*/

	}	while(rows!=0);                          //zjd
	//ifail = generation_num(TeZhengMa,length,number+step,&new_num);
	//printf("new_num = %s\n",new_num);
	//strcpy(counter_name,"%");
	//strcat(counter_name,new_num);
	//strcat(counter_name,"%");
	//printf("new_num of TeZhengMa=%s\n",counter_name);
	//ifail = EnqLikeNo(counter_name,&rows);
	//MEM_free(new_num);
	//printf("rows = %d\n",rows);	

	if(is_new||start_num>number)
	{
		ifail = POM_set_attr_int( 1, &instance, attr_id, start_num);

		//*sNum = start_num;
	}
	else
	{
		ifail = POM_set_attr_int( 1, &instance, attr_id, number+i);
		//*sNum = number+i;

	}

	//TEST_POM_ERROR(ifail)

	ifail = POM_save_instances( 1, &instance, true );
	TEST_POM_ERROR(ifail);

	printf("sNum = %s\n",*sNum);
	return ifail;
}

int GetSeqNo(char* TeZhengMa, int length, int start_num, int end_num,int step,int *sNum)
{
	int ifail;
	logical tagValid = false ;
	int number;
	int *rtn;
	char	counter_name[255];
	void *returnValueType;
	sprintf(counter_name,"%s$%d$%d$%d$%d",TeZhengMa,length,start_num,end_num,step);
	printf("counter_name = %s\n",counter_name);

	POM_is_tag_valid( instance , &tagValid);

	ifail = ORIGIN_select_counter(counter_name,start_num);
	TEST_ERROR(ifail)	

		ifail = load_current_number(counter_name,&number);
	printf("counter number = %d\n",number);
	if (!attr_ok)
	{
		ifail = get_next_id_attribute();
		TEST_ERROR(ifail)
	}
	if(is_new)

		ifail = POM_set_attr_int( 1, &instance, attr_id, start_num);

	else
	{
		if(number+step>end_num)
		{
			*sNum=number+step;
			return -1;
		}		
		ifail = POM_set_attr_int( 1, &instance, attr_id, number+step);
	}
	TEST_POM_ERROR(ifail)

		ifail = POM_save_instances( 1, &instance, true );
	TEST_POM_ERROR(ifail)
		//(int*)returnValueType = number+step;
		//printf("current_number = %d\n",number+step);
		//printf("returnValueType = %d\n",returnValueType);
		if(is_new)
			*sNum = start_num;
		else
			*sNum = number+step;

	return ifail;
	//return number+step;
	//return ITK_ok;
}


int SERVICE_part_no( void *retValType )
{
	int ifail = ITK_ok, i=0;
	char  
		*argTeZhengMa=NULL, strTeZhengMa[ITEM_id_size_c + 1] = "", 
		*new_num=NULL, counter_name[256] = "", temp[ITEM_id_size_c + 1] = "",
		*data = NULL;
	int   arg1 = 0, arg2 = 0, arg3 = 0, arg4 = 0, num = 0, rows = 0;

	//取得客户端java所传来的参数
	ifail = USERARG_get_string_argument(&argTeZhengMa);
	ifail = USERARG_get_int_argument(&arg1);
	ifail = USERARG_get_int_argument(&arg2);
	ifail = USERARG_get_int_argument(&arg3);
	ifail = USERARG_get_int_argument(&arg4);

	if(argTeZhengMa!=NULL)
	{
		strcpy(strTeZhengMa,argTeZhengMa);
	}

	//调用自己的方法，参数来自Java
	ifail = GetSeqNo(strTeZhengMa,arg1,arg2,arg3,arg4,&num);
	TEST_ERROR(ifail)	


	sprintf(temp,"%d",num);

	do
	{
		i++;
		ifail = generation_num(strTeZhengMa,arg1,num,&new_num);	

		//char counter_name[256] = "";
		strcpy(counter_name,"%");
		strcat(counter_name,new_num);
		strcat(counter_name,"%");
		ifail = EnqLikeNo(counter_name,&rows);
		if ( rows != 0 )
			free(new_num);

	} while(rows!=0 && i<10000);    

	if(num>arg3)
		strcpy(temp,"Error: Current WaterNumber is out of Max Value!");
	else
		sprintf(temp,"%s",new_num);

	//data = (char *) MEM_alloc ( sizeof(char)*(strlen(pszID) + 1 ) );
	printf("new_num= %s\n",new_num);

	data = (char *)MEM_alloc((ITEM_id_size_c + 1)*sizeof(char));
	strcpy( data, temp );
	*((char**) retValType) = data;
	MEM_free(new_num);

	printf( "new itemid = %s\n", *(char**)retValType);
	return ITK_ok;
}

int SERVICE_internal_part_no( const char *argMark, int length, int start_num, int end_num,int step, char **newID )
{
	int ifail = ITK_ok, i=0;
	char  
		strTeZhengMa[ITEM_id_size_c + 1] = "", 
		*new_num=NULL, counter_name[256] = "", temp[ITEM_id_size_c + 1] = "",
		*data = NULL;
	int   arg1 = length, arg2 = start_num, arg3 = end_num, arg4 = step, num = 0, rows = 0;

	if(argMark!=NULL)
	{
		strcpy( strTeZhengMa, argMark );
	}

	//调用自己的方法，参数来自Java
	ifail = GetSeqNo(strTeZhengMa,arg1,arg2,arg3,arg4,&num);
	TEST_ERROR(ifail)	
	sprintf(temp,"%d",num);

	do
	{
		i++;
		ifail = generation_num(strTeZhengMa,arg1,num,&new_num);	

		//char counter_name[256] = "";
		strcpy(counter_name,"%");
		strcat(counter_name,new_num);
		strcat(counter_name,"%");
		ifail = EnqLikeNo(counter_name,&rows);
		if ( rows != 0 )
			free(new_num);

	} while(rows!=0 && i<10000);    

	if(num>arg3)
		strcpy(temp,"Error: Current WaterNumber is out of Max Value!");
	else
		sprintf(temp,"%s",new_num);
	MEM_free(new_num);

	*newID = (char *)MEM_alloc((ITEM_id_size_c + 1)*sizeof(char));
	strcpy( *newID, temp );
	printf( "new itemid = %s\n", temp);
	return ITK_ok;
}


/**
* @}
*/