// C++ program to create calculator using
// switch statement
#include <iostream>
#include<unistd.h>
#include <curl/curl.h>
#include "nd_sdk.h"
using namespace std;

pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 

int count = 0;
ndBTHandle bthandle1 = NULL;
CURL *curl;

static void __attribute__((constructor)) calc_constructor(void) {
	nd_init2((char*)"sdk", (char*)"asynccalculator");
}

static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
	fprintf(stderr, "doing http callout \n");
	ndIPCallOutHandle icallout = nd_ip_http_callout_begin(bthandle1,"66.220.31.147","http://66.220.31.147:8080/nsecom/");
	nd_ip_http_callout_end(bthandle1,icallout);

    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}
int addheader = 0;
void SendRequestonServer() {
	CURLcode res;
  	std::string readBuffer;
  	struct curl_slist *chunk = NULL;
  	char header[1024];
  	if(curl) {
	    //curl_easy_setopt(curl, CURLOPT_URL, "http://66.220.31.147:8080/nsecom/");
	    curl_easy_setopt(curl, CURLOPT_URL, "http://10.20.0.85:81/PDO/pdo.php");
	    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
	    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

	    if(!addheader) {
		    char *cus_header = get_custom_nd_header(bthandle1);

		    if(cus_header) {
		    	snprintf(header, 1024, "%s:%s", "Cav2NDFPInstance", cus_header);
		    	fprintf(stderr, "cus_header %s\n", cus_header);
			    chunk = curl_slist_append(chunk, header);
			    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
			    //addheader = 1;
			}
		}
	    res = curl_easy_perform(curl);
    	std::cout << "data length " << res << std::endl;
  	}
}

void Displaysum(float num1, float num2, ndBTHandle bthandle) {
	nd_method_entry(bthandle,(char*)"pkg1.cls1.Displaysum");
	cout << "sum " << num1 + num2<<endl;
	nd_method_exit(bthandle,(char*)"pkg1.cls1.Displaysum");
}
void Displaydiff(float num1, float num2, ndBTHandle bthandle) {
	nd_method_entry(bthandle,(char*)"pkg1.cls1.Displaydiff");
	cout << "diff "<<num1 - num2<<endl;
	nd_method_exit(bthandle,(char*)"pkg1.cls1.Displaydiff");
}
void Displayproduct(float num1, float num2, ndBTHandle bthandle) {
	nd_method_entry(bthandle,(char*)"pkg1.cls1.Displayproduct");
	cout << "prod " << num1 * num2<<endl;
	nd_method_exit(bthandle,(char*)"pkg1.cls1.Displayproduct");
}
void Displaydiv(float num1, float num2, ndBTHandle bthandle) {
	nd_method_entry(bthandle,(char*)"pkg1.cls1.Displaydiv");
	cout << "div " << num1 / num2<<endl;
	nd_method_exit(bthandle,(char*)"pkg1.cls1.Displaydiv");
}

void * threadFunc1(void * arg)
{
	char *unique_bt_id_c = (char*)"2";
	float num1 = 100, num2 = 40;
	for(int i = 0;i < 10; i++) {
		char btname[50];

		sprintf(btname,"threadFunc1_%d",i);
		bthandle1 = nd_bt_begin(btname,NULL,NULL,NULL,NULL,NULL);
		nd_bt_store(bthandle1, unique_bt_id_c);

		Displaysum(num1, num2, bthandle1);
		Displaydiff(num1, num2, bthandle1);
		count = 1;
		pthread_cond_signal(&cond); 
		pthread_mutex_lock(&lock);
		while (count > 0)
	        pthread_cond_wait(&cond, &lock);
	    //fprintf(stderr, "reset1 %p\n",bthandle1);
	    count = 0;
	    pthread_mutex_unlock(&lock);
		num1++;
		num2++;
	}
	fprintf(stderr, "closing thread1\n");
    return NULL;
}

void * threadFunc2(void * arg)
{
	float num1 = 200, num2 = 140;
	int count_trans = 0;
	while(1) {
		pthread_mutex_lock(&lock);
	    while (count < 1)
	        pthread_cond_wait(&cond, &lock);
	    //fprintf(stderr, "reset2 %p\n",bthandle1);
	    pthread_mutex_unlock(&lock);

	    if(count_trans%2)
	    	SendRequestonServer();
		Displayproduct(num1, num2, bthandle1);
		Displaydiv(num1,num2, bthandle1);

		nd_bt_end(bthandle1,0);
		count = 0;
		pthread_cond_signal(&cond);
		num1++;
		num2++;
		count_trans++;
		if(count_trans >9)
			break;
		//sleep(1);
	}
	fprintf(stderr, "closing thread2\n");
    return NULL;
}

// Main program
int main()
{
  curl = curl_easy_init();

	pthread_t threadId1,threadId2;
	int err = pthread_create(&threadId1, NULL, &threadFunc1, NULL);
	err = pthread_create(&threadId2, NULL, &threadFunc2, NULL);

	pthread_join(threadId1, NULL);

	pthread_join(threadId2, NULL);
	pthread_mutex_destroy(&lock);
	curl_easy_cleanup(curl);

fprintf(stderr, "closing app\n" );
	return 0;
}

