#include "../src/hammer.h"
#include "dns_common.h"
#include "dns.h"

#define false 0
#define true 1

H_ACT_APPLY(act_index0, h_act_index, 0)

/**
 * A label can't be more than 63 characters.
 */
bool validate_label(HParseResult *p, void* user_data) {
  if (TT_SEQUENCE != p->ast->token_type)
    return false;
  return (64 > p->ast->seq->used);
}

#define act_label h_act_flatten

HParsedToken* act_domain(const HParseResult *p, void* user_data) {
  HParsedToken *ret = NULL;
  char *arr = NULL;

  switch(p->ast->token_type) {
  case TT_UINT:
    arr = " ";
    break;
  case TT_SEQUENCE:
    // Sequence of subdomains separated by "."
    // Each subdomain is a label, which can be no more than 63 chars.
    arr = h_arena_malloc(p->arena, 64*p->ast->seq->used);
    size_t count = 0;
    for (size_t i=0; i<p->ast->seq->used; ++i) {
      HParsedToken *tmp = p->ast->seq->elements[i];
      for (size_t j=0; j<tmp->seq->used; ++j) {
	arr[count] = tmp->seq->elements[i]->uint;
	++count;
      }
      arr[count] = '.';
      ++count;
    }
    arr[count-1] = '\x00';
    break;
  default:
    arr = NULL;
    ret = NULL;
  }

  if(arr) {
    dns_domain_t *val = H_ALLOC(dns_domain_t);  // dns_domain_t is char*
    *val = arr;
    ret = H_MAKE(dns_domain_t, val);
  }

  return ret;
}

HParser* init_domain() {
  static HParser *ret = NULL;
  if (ret)
    return ret;

  H_RULE  (letter,    h_choice(h_ch_range('a','z'), h_ch_range('A','Z'), NULL));
  H_RULE  (let_dig,   h_choice(letter, h_ch_range('0','9'), NULL));
  H_RULE  (ldh_str,   h_many1(h_choice(let_dig, h_ch('-'), NULL)));
  H_VARULE(label,     h_sequence(letter,
				 h_optional(h_sequence(h_optional(ldh_str),
						       let_dig,
						       NULL)),
				 NULL));
  H_RULE  (subdomain, h_sepBy1(label, h_ch('.')));
  H_ARULE (domain,    h_choice(subdomain, h_ch(' '), NULL));

  ret = domain;
  return ret;
}

HParser* init_character_string() {
  static HParser *cstr = NULL;
  if (cstr)
    return cstr;

  cstr = h_length_value(h_uint8(), h_uint8());

  return cstr;
}
