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

typedef struct _node {
  struct _node* left;
  struct _node* right;
  struct _node* child;
  long lvl;
  long key;
} node;

void visit_node_post_order(node *q, void (*callback)(node *)) {
  if (!q) {
    return;
  }

  visit_node_post_order(q->child, callback);
  visit_node_post_order(q->right, callback);
  callback(q);
}

void node_destroy(node *q) {
  void (*func)(node *) = (void (*)(node *))free;
  visit_node_post_order(q, func);
}

node* node_create(long key) {
  node *res = (node *)malloc(sizeof(node));
  res->lvl = 0;
  res->key = key;
  res->left = res;
  res->right = res;
  res->child = NULL;
  return res;
}

node* node_union_same_lvl(node* l, node* r) {
  if (!l) {
    return r;
  }

  if (!r) {
    return l;
  }

  if (l->lvl != r->lvl) {
    fprintf(stderr, "L lvl %d and R lvl %d do mismatch. Returning NULL\n", l->lvl, r->lvl);
    return NULL;
  }

  node* item;
  node* subitem;

  if (l->key > r->key) {
    // l main
    item = l;
    subitem = r;
  } else {
    // r main
    item = r;
    subitem = l;
  }

  if (item->child) {
    item->child->left->right = subitem; // we have two directional list (left,right links) where left of the beginning is the
                                      // end and right of the end is the beginning
  } else {
    item->child = subitem;
  }
  item->lvl++; // we merged two same lvl binomial heap nodes and created on lvl bigger

  return item;
}

node* node_add(node *q, long key) {
  node *c = NULL;
  node *a = q;
  node *b = node_create(key);

  if (q->lvl < 0) {
    return b;
  }

  while (a) {
    if (a->lvl > b->lvl) { // it a always will be bigger or equal
      b->right = a;
      a->left->right = b;
      b->left = a->left; // a's ending
      a->left = b;
      return b;
    } else {
      b = node_union_same_lvl(a, b);
      c = a->right;
      a->right = NULL;

      if (c == q) {
        break;
      }

      a = c;
    }
  }

  return b;

}

int node_del(node *q) {
  // TODO
  return -1;
}


const int MAX_BUFFER = 0x1000;

int main() {
  char cmd[MAX_BUFFER];
  node *q = (node *)malloc(sizeof(node));
  q->lvl = -1;
  q->key = 0xdeadbeaf; // it doesn't mother honestly
  while (1) {
    fgets(cmd, MAX_BUFFER, stdin);
    printf("Got command %s\n", cmd);

    if (strlen(cmd) == 0 || cmd[0] == '\n') {
      printf("Finished reading\n");
      break;
    } else if (memcmp(cmd, "ADD", 3) == 0) {
      // handle command add
      int x = atoi(cmd + 4);
       
      q = node_add(q, x);

      printf("Added number: %d\n", x);
  
    } else if (memcmp(cmd, "DEL", 3) == 0) {
      // handle command del
      if (!q) {
        fprintf(stderr, "There is nothing to delete - heap is empty\n");
        continue;
      }
      long key = node_del(q);
      printf("Removed element: %d\n", key);
    } else {
      // handle unknown command
      fprintf(stderr, "Got unknown command %s\n", cmd);
    }

  }

  if (!q) {
    node_destroy(q);
  }

  return 0;
}
