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

json_struct *json_new_struct(int type)
{
  json_struct *c = (json_struct *)malloc(sizeof(json_struct));
  if(c == NULL){
    fprintf(stderr, "memory allocation problem !\n");
    exit(1);
  }
  c->type = type;
  c->next = NULL;
  return c;
}
    
json_struct *json_new_string(char *string)
{
  json_struct *c = json_new_struct(JSON_STRING);
  c->u.string = string;
  return c;
}

json_struct *json_new_number(float number)
{
  json_struct *c = json_new_struct(JSON_NUMBER);
  c->u.number = number;
  return c;
}

json_struct *json_new_constant(int constant)
{
  json_struct *c = json_new_struct(JSON_CONSTANT);
  c->u.constant = constant;
  return c;
}


json_attr_val *json_new_attr_val(char *attr, json_struct *s, json_attr_val *next)
{
  json_attr_val *av = (json_attr_val *)malloc(sizeof(json_attr_val));
  if(av == NULL){
    fprintf(stderr, "memory allocation problem !\n");
    exit(1);
  }
  av->attr = strdup(attr);
  av->val = s;
  av->next = next;
  return av;
}

json_struct *json_new_avl(json_attr_val *avl)
{
  json_struct *c = json_new_struct(JSON_AVL);
  c->u.attr_val_list = avl;
  return c;
}

void json_print_struct(FILE *f, json_struct *s)
{
  if(s == NULL) return;
  if(s->type == JSON_AVL) json_print_avl(f, s);
  if(s->type == JSON_LIST)  json_print_list(f, s);
  if(s->type == JSON_STRING) json_print_string(f, s);
  if(s->type == JSON_NUMBER) json_print_number(f, s);
  if(s->type == JSON_CONSTANT) json_print_constant(f, s);
}

void json_print_avl(FILE *f, json_struct *s)
{
  json_attr_val *avl;
  int first = 1;
  fprintf(f, "{");
  for(avl = s->u.attr_val_list; avl; avl = avl->next){
    if(first) first = 0;
    else fprintf(f, ", ");
    fprintf(f, "%s : ", avl->attr);
    json_print_struct(f, avl->val);
  }
  fprintf(f, "}\n");
}

void json_print_list(FILE *f, json_struct *s)
{
  int first = 1;
  fprintf(f, "[");
  s = s->u.first;
  while(s){
    if(first) first = 0;
    else fprintf(f, ", ");
    json_print_struct(f, s);
    s = s->next;
  }
  fprintf(f, "]\n");
}

void json_print_string(FILE *f, json_struct *s)
{
  if(s->u.string)
    fprintf(f, "%s", s->u.string);
  else
    fprintf(f, "");
}

void json_print_number(FILE *f, json_struct *s)
{
  fprintf(f, "%f", s->u.number);

}

void json_print_constant(FILE *f, json_struct *s)
{
  if(s->u.constant == JSON_CONST_TRUE){ 
    fprintf(f, " true");
    return;
  }
  if(s->u.constant == JSON_CONST_FALSE){ 
    fprintf(f, " false");
    return;
  }
  if(s->u.constant == JSON_CONST_NULL){ 
    fprintf(f, " null");
    return;
  }
}

void json_free_struct(json_struct *s);

json_struct *json_new_list(json_struct *s)
{
  json_struct *c = json_new_struct(JSON_LIST);
  c->u.first = s;
  return c;
}

void json_free_list(json_struct *s)
{
  if(s){
    json_free_list(s->next);
    json_free_struct(s);
  }
}

void json_free_attr_val_list(json_attr_val *avl)
{
  if(avl){
    json_free_attr_val_list(avl->next);
    free(avl->attr);
    json_free_struct(avl->val);
    free(avl);
  }
}

void json_free_struct(json_struct *s)
{
  if(s == NULL) return;
  if(s->type == JSON_AVL) json_free_attr_val_list(s->u.attr_val_list);
  if(s->type == JSON_LIST)  json_free_list(s->u.first);
  if(s->type == JSON_STRING) free(s->u.string);
  free(s);
}