"use strict";

// const fs = require('fs');
// const {EOL} = require('os');

function log(v) {
	// console.log(v);
}

function merge_heap(a, b) {
	log('a', a);
	log('b', b);
	if (!a) {
		log('a is empty. Returning b');
		return b;
	}

	if (!b) {
		log('b is empty. Returning a');
		return a;
	}

	// a & b are non null

	if (a.value > b.value) {
		log(`a.value is bigger than b.value`);
		return merge_heap(b, a); // heap the top, the smallest
	}

	log('Merging a.right with b');
	a.right = merge_heap(a.right, b); // merging right as right is usually smaller
	// and should be more performent thus
	// a.right is not null as b is not null
	if (!a.left) {
		a.left = a.right;
		a.right = null;
		a.height = 1;
		return a; // a is already merged with b and having null right
	}

	let t;
	// we keep leftist tree intact as it's balanced to the left
	if (a.left.height < a.right.height) {
		t = a.left;
		a.left = a.right;
		a.right = t;
	}

	a.height = a.right.height + 1;
	return a;
}

function pop_heap(heap) {
	return merge_heap(heap.left, heap.right);
}

function insert_heap(heap, val) {
	return merge_heap(heap, {value: val, height: 1});
}

let values = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
let heap = {root: null};

// heap.root = merge_heap(heap.root, {value: 1, height: 1});
// heap.root = merge_heap(heap.root, {value: 2, height: 1});
// heap.root = merge_heap(heap.root, {value: 3, height: 1});
// heap.root = merge_heap(heap.root, {value: -1, height: 1});

if (false) {
	// naive way of creating leftist heap
	for (let el of values) {
		heap.root = merge_heap(heap.root, {value: el, height: 1});
	}
} else {
	// better way of creating heap using queue
	let queue = [];
	for (let el of values) {
		queue.push({value: el, height: 1});
	}

	while (queue.length > 1) {
		let h1 = queue.shift();
		let h2 = queue.shift();
		let h = merge_heap(h1, h2);
		queue.push(h);
	}

	heap.root = queue.shift();
}

while (heap.root) {
	let el = heap.root.value;
	console.log(`Value: ${el}`);
	heap.root = pop_heap(heap.root);
}
