#define __WEIGHBOR_C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "tree.h"
#include "matrix.h"
#include "io.h"
#include "weighbor.h"
#include "ancestral.h"

void transfer(int N,int nodeNo,NODE *node,RootNodeT *np);
void transfer1(int N,int nodeNo,NODE *node,NodeT *np);
int arrange;
void weighbor(int N, int sequenceLength, NODE *node, double **distMatrix,char *treeFile)
{

  int i, j;
  FILE *fp=stdout, *inputfp=stdin;

//  int N;            /* Number of taxa  */
  MatrixT D;        /* Distance Matrix */
  char **taxon;     /* names of taxa   */
  BooleanT lengthFlag = False; /* set if the -L option was given */

  RootNodeT *tree;
  MatrixT matrix(int);
  void printTree(FILE*, RootNodeT *);
  void deleteTree(RootNodeT *);
  RootNodeT *buildTree(int, MatrixT, char **);
//	printf("begin transfer value\n");
	L=sequenceLength;
	EPSILON=(EPS_BARE);
	MINB    = (MINB_BARE)/L;
	lengthFlag = True;
	B=20;
	sigBi=(1.0/B);
	sigBB=((B-1.0)/B);
	sigBBi=(B/(B-1.0));
//	N=seqNumber;
	D=matrix(N);
	for(i=1;i<=N;i++) for(j=1;j<=N;j++) D[i-1][j-1]=distMatrix[i][j];
	taxon=cmatrix(0,N,0,20);
	for(i=1;i<=N;i++) strcpy(taxon[i-1],node[i].nodeName);
	if(w_Flag==False) warnFlag=True;
	else warnFlag=False;
//	warnFlag=!(w_Flag);
//	printf("after transfer value\n");
	tree = buildTree(N, D, taxon);
//	node[N+1].dist=0.0;
//	fp=fopen("DISTMATRIX.tre","w");
	fp=fopen(treeFile,"w");
	printTree(fp, tree);
	fclose(fp);
	arrange=N+1;
	transfer(N,N+1,node,tree);
	deleteTree(tree);

	/*
	  Now free the memory used by the name strings
	  */

//	for(i=0;i<N;++i)
//	  free(taxon[i]);
//  	fclose(fp);
	printf("finish weighbor and return\n");
}

void transfer(int N,int nodeNo,NODE *node,RootNodeT *np)
{
	int nodeL,nodeM,nodeR;
	node[nodeNo].dist=0.0;
	node[nodeNo].rootFlag=true;
	node[nodeNo].parent=nodeNo;	
	if(LEAF(np->child_l)){
//		nodeL=nodeNo;
		for(int i=1;i<=N;i++){
			if(strcmp(node[i].nodeName,(np->child_l)->name)==0){
				node[nodeNo].childL=i;
				node[node[nodeNo].childL].parent=nodeNo;
				node[node[nodeNo].childL].dist=(np->child_l)->rho;
//				printf("nodeNo:%d dist:%8.5f\n",node[nodeNo].childL,node[node[nodeNo].childL].dist);
				break;
			}
		}
	}
	else {
//		nodeL=nodeNo+1;
		arrange++;
		node[nodeNo].childL=arrange;
		node[arrange].parent=nodeNo;
		transfer1(N,arrange,node,np->child_l);
	}
	if(LEAF(np->child_m)){
//		nodeM=nodeL;
		for(int i=1;i<=N;i++){
			if(strcmp(node[i].nodeName,(np->child_m)->name)==0){
				node[nodeNo].childE=i;
				node[node[nodeNo].childE].parent=nodeNo;
				node[node[nodeNo].childE].dist=(np->child_m)->rho;
//				printf("nodeNo:%d dist:%8.5f\n",node[nodeNo].childE,node[node[nodeNo].childE].dist);
				break;
			}
		}
	}
	else {
//		nodeM=nodeL+1;
		arrange++;
		node[nodeNo].childE=arrange;
		node[arrange].parent=nodeNo;
		transfer1(N,arrange,node,np->child_m);
	}
	if(LEAF(np->child_r)){
//		nodeR=nodeM;
		for(int i=1;i<=N;i++){
			if(strcmp(node[i].nodeName,(np->child_r)->name)==0){
				node[nodeNo].childR=i;
				node[node[nodeNo].childR].parent=nodeNo;
				node[node[nodeNo].childR].dist=(np->child_r)->rho;
//				printf("nodeNo:%d dist:%8.5f\n",node[nodeNo].childR,node[node[nodeNo].childR].dist);
				break;
			}
		}
	}
	else {
//		nodeR=nodeM+1;
		arrange++;
		node[nodeNo].childR=arrange;
		node[arrange].parent=nodeNo;
		transfer1(N,arrange,node,np->child_r);
	}
//	printf("nodeNo:%d childL:%d childE:%d childR:%d\n",nodeNo,node[nodeNo].childL,node[nodeNo].childE,node[nodeNo].childR);
}

void transfer1(int N,int nodeNo,NODE *node,NodeT *np)
{
	int nodeL,nodeR,childL=0,childR=0;
	node[nodeNo].dist=np->rho;
//	printf("nodeNo:%d dist:%8.5f\n",nodeNo,node[nodeNo].dist);
	if(LEAF(np->child_l)){
//		nodeL=nodeNo;
		for(int i=1;i<=N;i++){
			if(strcmp(node[i].nodeName,(np->child_l)->name)==0){
				node[nodeNo].childL=i;
				node[node[nodeNo].childL].parent=nodeNo;
				node[node[nodeNo].childL].dist=(np->child_l)->rho;
//				printf("nodeNo:%d dist:%8.5f\n",node[nodeNo].childL,node[node[nodeNo].childL].dist);
				break;
			}
		}
	}
	else {
//		nodeL=nodeNo+1;
		arrange++;
		node[nodeNo].childL=arrange;
		node[arrange].parent=nodeNo;
		transfer1(N,arrange,node,np->child_l);
	}
	if(LEAF(np->child_r)){
//		nodeR=nodeL;
		for(int i=1;i<=N;i++){
			if(strcmp(node[i].nodeName,(np->child_r)->name)==0){
				node[nodeNo].childR=i;
				node[node[nodeNo].childR].parent=nodeNo;
				node[node[nodeNo].childR].dist=(np->child_r)->rho;
//				printf("nodeNo:%d dist:%8.5f\n",node[nodeNo].childR,node[node[nodeNo].childR].dist);
				break;
			}
		}
	}
	else {
//		nodeR=nodeL+1;
		arrange++;
		node[nodeNo].childR=arrange;
		node[arrange].parent=nodeNo;
		transfer1(N,arrange,node,np->child_r);
	}
//	printf("nodeNo:%d childL:%d childR:%d\n",nodeNo,node[nodeNo].childL,node[nodeNo].childR);
//	if((childR>nodeR)&&(childR>childL)) return childR;
//	else if(childL>nodeR) return childL;
//	else return nodeR;
}	


