#include "rlang.h"
#include "decl/df-decl.h"


r_obj* r_alloc_df_list(r_ssize n_rows,
                       r_obj* names,
                       const enum r_type* v_types,
                       r_ssize types_size) {
  r_obj* out = KEEP(r_alloc_list(types_size));

  if (r_typeof(names) != R_TYPE_character) {
    r_abort("`names` must be a character vector.");
  }
  if (r_length(names) != types_size) {
    r_abort("`names` must match the number of columns.");
  }
  r_attrib_poke_names(out, names);

  for (r_ssize i = 0; i < types_size; ++i) {
    // A nil type stands for no column allocation
    enum r_type type = v_types[i];
    if (type != R_TYPE_null) {
      r_obj* col = r_alloc_vector(type, n_rows);
      r_list_poke(out, i, col);
    }
  }

  FREE(1);
  return out;
}


void r_init_data_frame(r_obj* x, r_ssize n_rows) {
  init_compact_rownames(x, n_rows);
  r_attrib_poke(x, r_syms.class_, r_classes.data_frame);
}
void r_init_tibble(r_obj* x, r_ssize n_rows) {
  r_init_data_frame(x, n_rows);
  r_attrib_poke(x, r_syms.class_, r_classes.tibble);
}

static
void init_compact_rownames(r_obj* x, r_ssize n_rows) {
  r_obj* rn = KEEP(new_compact_rownames(n_rows));
  r_attrib_poke(x, r_syms.row_names, rn);
  FREE(1);
}

static
r_obj* new_compact_rownames(r_ssize n_rows) {
  if (n_rows <= 0) {
    return r_globals.empty_int;
  }

  r_obj* out = r_alloc_integer(2);
  int* p_out = r_int_begin(out);
  p_out[0] = r_globals.na_int;
  p_out[1] = -n_rows;

  return out;
}
