#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
 
#include "./include/db_adaptor.h"

extern _db_cfg  db_cfg;


extern char *GetAsciiTime();

struct timeval tv;

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

int dbc_connect_host(u8 db_index)
{
	char host_info[128];
 	_db_link *db_ptr=NULL;
	unsigned int timeout = 20;
	MYSQL*tmp_conn = NULL;
	
	db_ptr = &db_cfg.db_link[db_index];	
	if(db_ptr->enable == 0 || db_ptr->conn_status == 1)
		return 0;
		
	if ((db_ptr->db_conn  = mysql_init(NULL)) == NULL) {
		myLOG_D("DBA: mysql_init():failed\n");
		return -1;
	}
	//unsigned int sslmode = SSL_MODE_DISABLED;
	mysql_options(db_ptr->db_conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&timeout);
	//mysql_options(db_ptr->db_conn, MYSQL_OPT_SSL_MODE, (const char *)&sslmode);
		
	sprintf(host_info,"%s", db_ptr->str_host_ip);

	tmp_conn = mysql_real_connect(db_ptr->db_conn, host_info, db_ptr->client_name, db_ptr->client_pwd, db_ptr->db_name, 0, NULL, 0 );

	if(tmp_conn != NULL)
	{
		db_ptr->conn_status = 1;
		db_cfg.total_active_links ++;
		myLOG_D("DBA: MYSQL connect to SERVER [%d] succeed @%s\n",  db_index, GetAsciiTime());		
	}
	else
	{
		db_ptr->conn_status = 0;
		myLOG_D("DBA: MYSQL connect to SERVER [%d] failed @%s, %s\n",  db_index, GetAsciiTime(), mysql_error(db_ptr->db_conn));
		mysql_close(db_ptr->db_conn);
		return -1;		
	}
	
	if(db_cfg.total_active_links == 1)
	{
		db_cfg.current_working_link_id = db_index;
	}
	
	
	return 1;	
}

MYSQL 	*dba_get_working_conn(int db_index)
{
	MYSQL 	*db_conn = NULL;
	//u8 	index = db_cfg.current_working_link_id;
	u8 index = db_index;
	
	if(db_cfg.total_active_links == 0)
		return NULL;
	if( index < MAX_DB_CONN)
	{
		db_conn = db_cfg.db_link[index].db_conn;
	}
	//*db_index = index;
	return db_conn;
}

int dba_close_conn(int index)
{
	if(index>=MAX_DB_CONN)
		return 0;
	
	//mysql_close(db_cfg.db_link[index].db_conn);	
	//free(db_cfg.db_link[index].db_conn);
	
	db_cfg.db_link[index].conn_status = 0;
	db_cfg.total_active_links --;

	return 1;
}

int dba_my_ping()
{
	int i;
	int length;
	char ping_sql[256]={"Replace" };
	MYSQL 		*db_conn;
	int   rc;

	for(i=0; i<MAX_DB_CONN; i++)
	{
		if(db_cfg.db_link[i].conn_status == 0)
			continue;
		
		db_conn = db_cfg.db_link[i].db_conn;
		if(db_conn == NULL)
			continue;
			
		sprintf(ping_sql, "INSERT INTO %s.tb_ping values(%ld)", db_cfg.db_link[i].db_name, tv.tv_sec);
		length = strlen(ping_sql);
	
		rc = mysql_real_query(db_conn, ping_sql, length);
		if(rc != 0)
		{
		    myLOG_D("DBA: Server [%d] is down by ping @%s error [errno = %d]: [%s]\n", i, GetAsciiTime(), mysql_errno(db_conn),mysql_error(db_conn));

		    dba_close_conn(i);
			
		    if(db_cfg.current_working_link_id == i)
		    {
		    	if(db_cfg.db_link[1-i].conn_status == 1) //here only support 2 links
		    	{
		    		db_cfg.current_working_link_id = 1 - i;
		    	}
		    	else
		    		db_cfg.current_working_link_id = INVALID_DB_LINK_ID;
		    }	
		}
	}
	 
	return 1;
}

dba_db_sql_execute_crm(const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS, int dump_flag, FILE *fp)
{
	int index = 0;

	return dba_db_sql_execute_real(index, sql, result, MAX_ROWS, MAX_FIELDS, dump_flag, fp);
}

dba_db_sql_execute_ocs(const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS, int dump_flag, FILE *fp)
{
	int index = 1;

	return dba_db_sql_execute_real(index, sql, result, MAX_ROWS, MAX_FIELDS, dump_flag, fp);
}



int dba_db_sql_execute_real(int index, const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS, int dump_flag, FILE *fp)
{
	int 		rc;
	int           i, rows, fields;	
	u16 		length;
	MYSQL 		*db_conn;
	MYSQL_RES 	*res_ptr;
	MYSQL_ROW       row;

	if(sql == NULL)
		return 0;
		
	db_conn = dba_get_working_conn(index);
	if(db_conn == NULL)
		return 0;

	if(0)
	{
		if(dump_flag != 2)
		{
			if(strlen(sql)<256)
			{
				myLOG_D(sql);
				myLOG_D("\n");
			}
			else
			{
				char tmpbuf[512]={""};
				memcpy(tmpbuf, sql, 256);
				myLOG_D(tmpbuf);
				myLOG_D("\n");
				
			}
		}
	}
	
	length = strlen(sql);
	rc = mysql_real_query(db_conn, sql, length);
	if(rc != 0)
	{
		myLOG_D("mysql_real_query error [errno = %d]: [%s]\n",mysql_errno(db_conn),mysql_error(db_conn));
		dba_close_conn(index);
	    //release_mysql_connection(db_conn);
		return 0;
	}
	if(MAX_ROWS == 0)//update not query
		return 1;
	
	res_ptr = mysql_store_result(db_conn);
	if(res_ptr == NULL)
	{
		myLOG_D("mysql_store_result error [errno = %d]: [%s]\n",mysql_errno(db_conn),mysql_error(db_conn));
		return 0;
	}

	rows = mysql_num_rows(res_ptr);
	if(rows == 0)
		goto empty;

	rows = 0;
	fields = mysql_num_fields(res_ptr);
	if(fields > MAX_FIELDS)
		fields = MAX_FIELDS;
	while ((row = mysql_fetch_row(res_ptr))) 
	{
		if(dump_flag == 1)
		{
			if(fp != NULL)
			{
				for (i = 0; i < fields; i++)
				{
					if(i == fields - 1)
						fprintf(fp, "%s\r\n", row[i]);
					else
						fprintf(fp, "%s,", row[i]);						
				}
			}
		}
		else
		{
			for (i = 0; i < fields; i++)
			{
				if(row[i] == NULL)
				{
					result[i][0] = 0;
					if(0)
					{
						fields = 0;
						rows = 0;
						goto empty;
					}
				}
				else
					strcpy(result[i], row[i]);
			}
		}
		if(rows++ >= MAX_ROWS)
			break;
	}

empty:	
	mysql_free_result(res_ptr);  	

	return rows;//fields;	
}

static int sql_query_only_counter = 0;
int dba_db_sql_query_only_execute_real(const char *sql, char result[][1024], int MAX_ROWS, int MAX_FIELDS )
{
	int 		index;
	_db_link   *db_ptr=NULL;

	//load balance for tariff query, db_conn#1/2 always
	if(sql == NULL)
		return 0;

	index = 	sql_query_only_counter%2;
	sql_query_only_counter ++;

	db_ptr = &db_cfg.db_link[index+1];	
	if(db_ptr->enable == 0 || db_ptr->conn_status == 1)
	{
		db_ptr = &db_cfg.db_link[(1-index)+1];	
		if(db_ptr->enable == 0 || db_ptr->conn_status == 1)
		{
			return 0;
		}
		else
			index = (1-index) + 1;
	}
	else
		index = index + 1;

	return dba_db_sql_execute_real(index, sql, result, MAX_ROWS, MAX_FIELDS, 0, NULL);
	
}

int dba_conn_thread(void *param)
{
	register u32 check_conn_timer = 1;
	register u32 check_sms_notification_timer = 0;

	db_cfg.current_working_link_id = INVALID_DB_LINK_ID;

	gettimeofday(&tv, NULL);

	dba_init_tariff_sql();
	crm_pxy_plan_record_init();
	
	while(1)
	{
		if(check_conn_timer % 1000 == 0)//10s
		{
			dbc_connect_host(0);
			dbc_connect_host(1);
			//dbc_connect_host(2);

			if(0)
				dba_my_ping();

			gettimeofday(&tv, NULL);

			crm_pxy_plan_record_timer();

		}
		
	      if(dba_crm_get_prefix_table_flag() == 0)
	      	{
	      		dba_crm_dump_prefix_table_into_file();
	      	}

		if(rest_provsioning_enabled())
		{
			
			if(check_sms_notification_timer%100 == 0) //1seconds==>2S 100==>200
			{
				subs_provisioning_command_process();
#if 1//def ENABLE_CRM_REST_AND_Z1
				sms_notification_process();
#endif
				//dba_crm_scan_bundle_thread(tv.tv_sec);
			}
		}
		
		logWriter_rt();

		check_conn_timer ++;	
		check_sms_notification_timer ++;

		usleep(10000); //10ms

	}
	
	return 1;
}
