
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sqlite3.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "tree.h"
#include "tcpClient.h"

Tree **tree;
Branch **branch;
static int branchCount=0;
static int treeCount=0;

///////////////////////////////
static int treeCountCallback(void *notused, int argc, char **argv, char **azColName) {

	for (int i = 0; i < argc; ++i) {
		if (!argv[i]) {
			continue;
			}
		printf("treeCountCallback: %s = %s\t", azColName[i], argv[i] ? argv[i]:"NULL");
		treeCount = atoi(argv[i]);
		printf("treeCount: %d\n", treeCount);
		}
	return(0);
	}


///////////////////////////////
static int treeCallback(void *data, int argc, char **argv, char **azColName) {
	int *row_index = (int*)data;

	for (int i = 0; i < argc; ++i) {
		if (!argv[i]) {
			continue;
			}
		if (strcmp(azColName[i], "ID") == 0) {
			strcpy(tree[*row_index]->ID, argv[i]);
			}
		else if (strcmp(azColName[i], "x") == 0) {
			tree[*row_index]->x = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "y") == 0) {
			tree[*row_index]->y = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "diameter") == 0) {
			tree[*row_index]->radiusBase = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "height") == 0) {
			tree[*row_index]->height = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "species") == 0) {
			strcpy(tree[*row_index]->species,argv[i]);
			}
		else if (strcmp(azColName[i], "texture") == 0) {
			strcpy(tree[*row_index]->texture,argv[i]);
			}
		}
	(*row_index)++;
	return(0);
	}

///////////////////////////////
static int branchCountCallback(void *notused, int argc, char **argv, char **azColName) {

	for (int i = 0; i < argc; ++i) {
		if (!argv[i]) {
			continue;
			}
//			printf("%s = %s\t", azColName[i], argv[i] ? argv[i]:"NULL");
		branchCount = atoi(argv[i]);
		}
	return(0);
	}


///////////////////////////////
//----Branch structure-----------
/*
typedef struct {
    void *parent; // cast to Trunk or Branch
    char ID[6];
    float height;
    float azimuth;
    float angle;
    float length;
    float diameter;
    float curvature;
    char texture[64];
    } Branch;
*/
//---------------------------------
static int branchCallback(void *data, int argc, char **argv, char **azColName) {
	int *row_index = (int*)data;

	for (int i = 0; i < argc; ++i) {
		if (!argv[i]) {
			continue;
			}
		if (strcmp(azColName[i], "ID") == 0) {
			strcpy(branch[*row_index]->ID, argv[i]);
			}
		else if (strcmp(azColName[i], "parentID") == 0) {
			strcpy(branch[*row_index]->parentID, argv[i]);
			}
		else if (strcmp(azColName[i], "position") == 0) {
			branch[*row_index]->height = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "azimuth") == 0) {
			branch[*row_index]->azimuth = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "angle") == 0) {
			branch[*row_index]->angle = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "length") == 0) {
			branch[*row_index]->length = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "diameter") == 0) {
			branch[*row_index]->diameter = atof(argv[i]);
			}
		else if (strcmp(azColName[i], "texture") == 0) {
			strcpy(branch[*row_index]->texture, argv[i]);
			}
		//printf("%s = %s  ", azColName[i], argv[i] ? argv[i]:"NULL");
		}

	int i = *row_index;
	printf("branch num %2d: ID: %s / %s, pos: %.2f, azimuth: %.1f angle: %.1f, length: %.1f, diam %.1f (%s)\n", i,
			branch[i]->ID, branch[i]->parentID, branch[i]->height, branch[i]->azimuth, branch[i]->angle,
			branch[i]->length, branch[i]->diameter, branch[i]->texture);

	(*row_index)++;

	return(0);
	}



/////////////////////////////////////////
//	get the number of trees, the treeCount
//	Malloc the array of trees
//	
//-----------------------------
int main(int argc, char **argv) {
	sqlite3 *db;
	char *err_msg = 0;
	int rc;
	const char *dBName = "orchard.db";
	char sql_cmd[128];
	int rowCounter = 0;

	rc = sqlite3_open(dBName, &db);
	if (rc != SQLITE_OK) {
		printf("can't open dB (%s)\n", dBName);
		sqlite3_close(db);
		return 1;
		}

//	rowCounter = 0;
	sprintf(sql_cmd, "select count(*) from tree;");
	rc = sqlite3_exec(db, sql_cmd, treeCountCallback, /*&rowCounter*/ 0, &err_msg);
	if (rc != SQLITE_OK) {
		printf("can't exec %s\n", sql_cmd);
		sqlite3_close(db);
		return 1;
		}
	printf("%d trees\n", treeCount);
	tree = (Tree **)malloc(sizeof(Tree *));
	for (int i= 0; i < treeCount; ++i) {
		tree[i] = (Tree *)malloc(sizeof(Tree));
		}

	rowCounter = 0;
	sprintf(sql_cmd,(char *)"select * from tree;");
	rc = sqlite3_exec(db, sql_cmd, treeCallback, &rowCounter, &err_msg);
	if (rc != SQLITE_OK) {
		printf("can't exec %s\n", sql_cmd);
		sqlite3_close(db);
		return 1;
		}
	for (int i= 0; i < treeCount; ++i) {
		printf("(%s) species: (%s) texture (%s)\n", tree[i]->ID, tree[i]->species, tree[i]->texture);
		}

	//------------for all the branches in the orchard-------------------
	rowCounter = 0;
	sprintf(sql_cmd, "select count(*) from branch;");
	rc = sqlite3_exec(db, sql_cmd, branchCountCallback, &rowCounter, &err_msg);
	if (rc != SQLITE_OK) {
		printf("can't exec %s\n", sql_cmd);
		sqlite3_close(db);
		return 1;
		}
	branch = (Branch **)malloc(sizeof(Branch *));

	for (int j= 0; j < branchCount; ++j) {
		branch[j] = (Branch *)malloc(sizeof(Branch));
		}

	rowCounter = 0;
	sprintf(sql_cmd, "select * from branch ;");
	rc = sqlite3_exec(db, sql_cmd, branchCallback, &rowCounter, &err_msg);
	if (rc != SQLITE_OK) {
		printf("can't exec %s\n", sql_cmd);
		sqlite3_close(db);
		return 1;
		}
	for (int j = 0; j < treeCount; ++j) { printf("tree[%d] @ %p\t", j, tree[j]); }

	printf("\n%d branches\n", branchCount);
	
	for (int i = 0; i < branchCount; ++i) {
/*
		printf("branch[%d] @ %p (%s)\t", i,  branch[i]->parent, branch[i]->parentID);
		for (int j = 0; j < treeCount; ++j) {
			printf("[%s/%s] ", tree[j]->ID, branch[i]->parentID);
			if (strcmp(branch[i]->parentID, tree[j]->ID) == 0) {
				branch[i]->parent = (void *)tree[j];
				break;
				}
			printf("*");
			}
*/
//		printf("branch[%d] @ %p (%s)\n", i, branch[i]->parent, branch[i]->parentID);

		printf("branch %2d: ID: %s, parent %s, azimuth: %.1f angle: %.1f, length: %.1f, diam %.1f (%s)\n", i,
			branch[i]->ID, branch[i]->parentID, branch[i]->azimuth, branch[i]->angle,
			branch[i]->length, branch[i]->diameter, branch[i]->texture);
		}

	sqlite3_close(db);

	////////////////////////////////////////////
	//	now play with the socket---------------
	// CLEAR
	// TRUNK X=0 Y=0 Z=0 HEIGHT=2.5 RBASE=0.08 RTOP=0.04
	// TRUNK X=2 Y=0 Z=0 HEIGHT=2.4 RBASE=0.08 RTOP=0.04
	//
	uint16_t port = 5000;
	char ip[20];
	strcpy(ip, "127.0.0.1");
	int sockfd = tcpClient(ip, port);
	if (sockfd < 0) {
		printf("returning with error\n");
		return(-1);
		}
	printf("opened socket @ %d\n", sockfd);

	char buffer[128];

	strcpy(buffer, "CLEAR\n");
	int n = strlen(buffer);	
	if (write(sockfd, buffer, n) < 0) {
		perror("write sockfd");
		return(-1);
		}
//	printf("Buffer: (%s)\n", buffer);
	usleep(1000*800);

	for (int i = 0; i < treeCount; ++i) {
		sprintf(buffer, "TREE X=%.2f Y=%.2f Z=0 HEIGHT=%.2f RBASE=%.2f RTOP=%.2f\n", 
						tree[i]->x, tree[i]->y, tree[i]->height, tree[i]->radiusBase, tree[i]->radiusTop);
		printf("tree buffer: (%s", buffer);
		int n = strlen(buffer);	
		if (write(sockfd, buffer, n) < 0) {
			perror("write sockfd");
			return(-1);
			}

		printf("tree %d: %s, branchCount %d\n", i, tree[i]->ID, branchCount);
		for (int j = 0; j < branchCount; ++j) {
			if (strcmp(branch[j]->parentID, tree[i]->ID)==0) {
				sprintf(buffer, "BRANCH HEIGHT=%.2f LENGTH=%.2f AZIMUTH=%.2f ANGLE=%.2f\n", 
						branch[j]->height, branch[j]->length, branch[j]->azimuth, branch[j]->angle);
				printf("branch buffer: (%s", buffer);
				int n = strlen(buffer);	
				if (write(sockfd, buffer, n) < 0) {
					perror("write sockfd");
					return(-1);
					}
				usleep(1000*500);
				}
			}
		}


	close(sockfd);
	return(0);
	}
