// include guard
#ifndef AVLC_H
#define AVLC_H

#include <memory>
#include <string>

class AVLCommands;

class BSTNode {
 public:
 	BSTNode(int key);
 	BSTNode(int key, std::weak_ptr<BSTNode> parent);
 	bool IsLeaf() const;
 	bool IsMissingChild() const;
 	bool HasLeftChild() const;
 	bool HasRightChild() const;
 	void DeleteChild(std::shared_ptr<BSTNode> v);
 	void ReplaceChild(std::shared_ptr<BSTNode> v, std::shared_ptr<BSTNode> u);

 private:
  int key_;
  std::weak_ptr<BSTNode> parent_;
  std::shared_ptr<BSTNode> left_;
  std::shared_ptr<BSTNode> right_;
  int height_;
  int balance_;

  //friend BST;
  friend AVLCommands;
}; // class BSTNode

class AVLCommands {
 public:
 	AVLCommands();

 	void Insert(int key);
 	bool Delete(int key);
 	bool Find(int key) const;
 	std::string JSON() const;
 	size_t size() const;
 	bool empty() const;
 	int DeleteMin();
  void printTree();

 private:
  int max(int a, int b);
  int height(std::shared_ptr<BSTNode> currentNode);
  void balance(std::shared_ptr<BSTNode> currentNode);
  std::shared_ptr<BSTNode> rightRotate(std::shared_ptr<BSTNode>);
  std::shared_ptr<BSTNode> leftRotate(std::shared_ptr<BSTNode>);
  void DeleteLeaf(std::shared_ptr<BSTNode> currentNode);
  int DeleteMin(std::shared_ptr<BSTNode> currentNode);
  void printTree(std::shared_ptr<BSTNode> currentNode);

 	std::shared_ptr<BSTNode> root_;
 	size_t size_;
}; // class BST

#endif
