/* This file contains the definition for class DecisionTree.

---------------------------------------------------------------*/

#include "DecisionTree.h"

DecisionTree::DecisionTree(void)
{
  Root = 0;
}

#include <string.h>

DecisionTree::Node::Node(char* String,
                         DecisionTree::NodePtr Left,
                         DecisionTree::NodePtr Right)
{
  strcpy(Buffer, String);

  Yes = Left;
  No = Right;
}

DecisionTree::~DecisionTree(void)
{
  if (Root != 0)
    delete Root;
}

DecisionTree::Node::~Node(void)
{
  if (Yes != 0)
    delete Yes;

  if (No != 0)
    delete No;
}

#include <stdlib.h>

int DecisionTree::Load(char* FileName)
{
  fstream
    InF(FileName, ios::in);

  if (InF.bad())
  {
    cerr << "\nDecisionTree: unable to open input file!\n";
    exit (-1);
  }

  BuildTree(InF, Root);

  InF.close();

  return 0;
}

void DecisionTree::BuildTree(istream& InF, DecisionTree::NodePtr& NPtr)
{
  char
    Buf[DecisionTree::Node::ArraySize];
  int
    Leftsubtree,
    Rightsubtree;
  char
    Return;

  if (!InF.eof())
  {
    InF.getline(Buf,DecisionTree::Node::ArraySize);
    InF >> Leftsubtree >> Rightsubtree;
    InF.get(Return);

    NPtr = new Node(Buf);

    if (Leftsubtree)
      BuildTree(InF, NPtr->Yes);

    if (Rightsubtree)
      BuildTree(InF, NPtr->No);
  }
}

int DecisionTree::Descend(void)
{
  char
    Answer;

  if ((Root != 0) && (Root->Yes == 0) && (Root->No == 0))
  {
    do
    {
      cout << "\nIs it a(n) " << Root->Buffer << " (y or n)? ";
      cin >> Answer;
    }
    while ((Answer != 'y') && (Answer != 'n'));

    if (Answer == 'y')
      return 1;
    else
      return 0;

  }
  else
  {
    do
    {
      cout << endl << Root->Buffer << " (y or n)? ";
      cin >> Answer;
    }
    while ((Answer != 'y') && (Answer != 'n'));

    if (Answer == 'y')
      return DescendTree(Root->Yes);
    else
      return DescendTree(Root->No);
  }
}


int DecisionTree::DescendTree(NodePtr& NPtr)
{
  char
    Answer;

  if (NPtr != 0)
    if ((NPtr->Yes == 0) && (NPtr->No == 0))
    {
      do
      {
        cout << "\nIs it a(n) " << NPtr->Buffer << " (y or n)? ";
        cin >> Answer;
      }
      while ((Answer != 'y') && (Answer != 'n'));

      if (Answer == 'y')
        return 1;
      else
      {
        LearnSomething(NPtr);
        return 0;
      }
    }
    else
    {
      do
      {
        cout << endl << NPtr->Buffer << " (y or n)? ";
        cin >> Answer;
      }
      while ((Answer != 'y') && (Answer != 'n'));

      if (Answer == 'y')
        return DescendTree(NPtr->Yes);
      else
        return DescendTree(NPtr->No);
    }
}

void DecisionTree::LearnSomething(NodePtr& NPtr)
{
  char
    Buf[DecisionTree::Node::ArraySize],
    Return;

  cout << "\nWhat animal are you thinking of? ";
  cin.get(Return);
  cin.getline(Buf, DecisionTree::Node::ArraySize);

  NodePtr
    AnimalPtr = new Node(Buf),
    TempPtr = NPtr;

  cout << "\nPlease enter a question, such that the answer is\n"
       << "\tyes - for a(n) " << Buf
       << " , and\n\tno - for a(n) " << NPtr->Buffer
       << "\n--> ";
  cin.getline(Buf,DecisionTree::Node::ArraySize);

  NPtr = new Node(Buf);

  NPtr->Yes = AnimalPtr;
  NPtr->No = TempPtr;
}



int DecisionTree::Write(char* FileName)
{
  fstream
    OutF(FileName, ios::out);

  if (OutF.bad())
  {
    cerr << "\nDecisonTree: unable to open output file!\n";
    exit (-1);
  }

  WriteTree(OutF, Root);

  OutF.close();

  return 0;
}


void DecisionTree::WriteTree(ostream& OutF, DecisionTree::NodePtr NPtr)
{
  if (NPtr != 0)
  {
    OutF << NPtr->Buffer << endl
         << (NPtr->Yes != 0) << ' '
         << (NPtr->No != 0) << endl;

    WriteTree(OutF, NPtr->Yes);
    WriteTree(OutF, NPtr->No);
  }
}

