

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

char *       statesStr[] = { "Error   ", "Variable", "Constant", "Operator", "Whitespace", "Parenthisis", "Function"};


void eqLL_Append(  eqLL_t * this,  states_t type, char * detail , int * priority ){

   eqNode_t * tempNode;
   
   tempNode = NULL;
 
   eqNode_CreateNode(  &tempNode, type, detail , priority) ;
   eqNode_AppendNode(  &this->Tail, &tempNode);  
     
   if (!this->Head) 
      this->Head = this->Tail;  // the first node
   else 
      this->Tail = this->Tail->rhs;       
         
   return;      
} 
      
void eqLL_Insert(  eqLL_t * this,  states_t type, char * detail , int * priority ){

   eqNode_t * tempNode;
   
   tempNode = NULL;
 
   eqNode_CreateNode(  &tempNode, type, detail , priority) ;
   eqNode_PrependNode(  &this->Head, &tempNode);  
     
   if (!this->Head) 
      this->Tail = this->Head;  // the first node
   else 
      this->Head = this->Head->lhs;       
         
   return;      
}       

// delete that from this.
void eqLL_Delete(  eqLL_t * this,  eqNode_t * that ){
  if (0) {
  } else if (this->Head == that) {
    this->Head = that->rhs;    
  } else if (this->Tail == that) {
    this->Tail = that->lhs;    
  } 
  eqNode_DeleteNode(that);
  return;
}
    
void eqLL_Show(eqLL_t * this) {

 eqNode_t * iter;

 //printf("Tail: %X   Head: %X\n", this->Tail, this->Head);

 for(iter = this->Head; iter; iter = iter->rhs) {
    eqNode_Show(iter);
 }

}   
         
void eqLL_Init(        eqLL_t * this ) {
  this->Head = NULL;
  this->Tail = NULL;
  return;
}
      
void eqLL_Fini(        eqLL_t * this ) {

 eqNode_t * cur, * next;
 

 for(cur = this->Head; cur;   ) {
    next = cur->rhs;
    eqNode_DeleteNode(cur);
    cur = next;
 }
 this->Head = this->Tail = NULL;
 
}
     
   
/**********************************************************************************************************/   
   
/*
 problem deleting the head node, cause teh head pointer, which we cant reach at this level, will be wrong.
 the same thing would happen with the tail node, but we dont really use that.

*/
void eqNode_DeleteNode(eqNode_t * this){
  // printf("Delete: ");
  // eqNode_Show( this) ;
   
   if (this->rhs != NULL)  this->rhs->lhs = this->lhs;
   if (this->lhs != NULL)  this->lhs->rhs = this->rhs;
   
   free(this->detail);
   free(this);
   this = NULL;

}
                   
void eqNode_SetType( eqNode_t * this, states_t type){
  this->type = type;
}

void eqNode_SetDetail( eqNode_t * this, char * detail) {
  this->detail = strdup(detail);
}

void eqNode_SetPriority( eqNode_t * this, int  priority) {
  this->priority = priority;
}

void eqNode_ClearPoints( eqNode_t * this ) {
  this->lhs = NULL;
  this->rhs = NULL;
}


void eqNode_CreateNode( eqNode_t ** this, states_t type, char * detail , int * priority) {
  *this = malloc(sizeof(eqNode_t));
  eqNode_SetType(     *this, type    );
  eqNode_SetDetail(   *this, detail  );
  eqNode_ClearPoints( *this );
  if (priority) eqNode_SetPriority( *this, *priority);
  else eqNode_SetPriority( *this, 0);
}


void eqNode_AppendNode( eqNode_t ** this, eqNode_t ** add){
  if (*this) {
    (*add)->rhs  = (*this)->rhs;
    (*add)->lhs  = *this;  
    (*this)->rhs = *add;
  } else {  // new list;
    *this = *add;
    (*add)->lhs = NULL;
    (*add)->rhs = NULL;
  }
 
}


void eqNode_PrependNode(eqNode_t ** this, eqNode_t ** add){

  if (*this) {
    (*add)->rhs  = *this;
    (*add)->lhs  = (*this)->lhs;  
    (*this)->lhs = *add;
  } else {
    *this = *add;
    (*add)->rhs = NULL;
  }
 
}


void eqNode_Show(eqNode_t * this) {
 if (this) {
    printf("Type: %s   Content: \"%s\"   Priority: %03d ", statesStr[this->type], this->detail, this->priority);
    printf("  lhs: %08X  is: %08X  rhs:%08X \n", this->lhs, this,  this->rhs);
 }
}

/*
int main (void) {

  eqLL_t   myeq;
  int      zero = 0;
  
  eqLL_Init(&myeq);
  eqLL_Append(  &myeq,  VAR, "rue_mohr" , &zero);
  eqLL_Append(  &myeq,  OPER, "this" , &zero);
  zero = 2;
  eqLL_Insert(  &myeq,  CONST, "that" , &zero);
  eqLL_Show( &myeq);
  
  printf("----------\n");
  
  eqNode_DeleteNode(myeq.Head->rhs);
  
  eqLL_Show( &myeq);
  
  eqLL_Fini( &myeq);
  
  printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
  
  eqLL_Show( &myeq);
  return 0;
}
*/
