/*
 * demo.dml
 *
 * This program demonstrates some of the simple features of the network DML
 * by maintaining a simple database of student room assignments.
 *
 * The following steps should be taken to generate an executable program, 
 * assuming that the DDL is contained within the file "demo.ddl";
 *
 * - run the preprocessor (netpp)
 * - type "demo.ddl" at the preprocessor's prompt
 * - compile the file output by the preprocessor (demo.cc) using a C++ compiler
 * - link the resulting object file with the NETSIM library
 * - run the resulting executable file
 *
 * At this point the following files will be in existence;
 *
 * - DDL source file (demo.ddl)
 * - DML application program source (demo.dml)
 * - translated C++ source, DDL, and DML (demo.cc)
 * - object file from C++ compilation (i.e. demo.obj/demo.o)
 * - executable version of application program (i.e. demo.exe/demo)
 * - database files created by first run of the program (student.dat, room.dat)
 *
 */

#include <string.h>
#include <iostream.h>
#include <bool.h>

#ddl "demo"

/******************************************************************************/

  int menu()
  // Offer the user a choice of options and return the one chosen.

  { const int screenLines = 24;
    const char ESC = '\033';
    bool ok;
    int choice;

    do
      { // Clear the screen.

        /* ~~~ This works on all machines, but is painful
        for (int i = 0; i < screenLines; i++)
          cout << endl;
        */

        /* This works on terminal that emulate a VT1xx or newer */

        cout << ESC << "[H" << ESC << "[J" << flush;

        // Display menu and get user choice.

        cout << " 1: Add Student" << endl
             << " 2: Add Room" << endl
             << " 3: Put Student In Room" << endl
             << " 4: Remove Student From Room" << endl
             << " 5: Change Room" << endl
             << " 6: Display Student Room" << endl
             << " 7: Display Room Students" << endl
             << " 8: Display All Students" << endl
             << " 9: Display All Rooms" << endl
             << "10: Change Student GPA" << endl
             << "11: Delete Student" << endl
             << "12: Delete Room" << endl
             << "13: Call the Interactive Debugger" << endl << endl;

        cout << "Choice (0 to exit)? ";

        cin >> choice;
        while (! cin.eof() && cin.get() != '\n') ;      // "readln"

        if (choice >= 0 && choice <= 13)
          ok = true;
        else
          {
            cout << "Please enter an integer from 0 to 13" << endl;
            ok = false;
            while (! cin.eof() && cin.get() != '\n') ;
          }
                
      } while (! ok);   // do

   return choice;

  }

void addStudent()
{ // Add a new student to students 

  char name[20];

  cout << "Last: ";
  cin >> name;
  strncpy(student.lastName, name, sizeof(student.lastName));
  cout << "First: ";
  cin >> name;
  strncpy(student.firstName, name, sizeof(student.firstName));

  // Date arrive is initialized to today by default constructor

  student.gpa = 0.0;
  while (! cin.eof() && cin.get() != '\n') ;

  #store student;

  if (Netsim::status != Netsim::SUCCESS)
    Netsim::signal(false);

}

void addRoom()
{ // Add a new room to rooms

  char dorm[15];

  cout << "Dorm: ";
  cin >> dorm;
  strncpy(room.dorm, dorm, sizeof(room.dorm));
  cout << "Number: ";
  cin >> room.number;
  while (! cin.eof() && cin.get() != '\n') ;

  #store room;

  if (Netsim::status != Netsim::SUCCESS)
    Netsim::signal(false);

}


void putStudentInRoom()
{ // Assign a student to a room

  char name[20];
  char dorm[15];

  cout << "Last: ";
  cin >> name;
  while (! cin.eof() && cin.get() != '\n') ;

  strncpy(student.lastName, name, sizeof(student.lastName));
  #find first student using lastName;
  if (Netsim::status != Netsim::SUCCESS)
    cout << "No such student" << endl;
  else
    {
      #if (isMember occupiedBy)
        cout << "Student is already in a room" << endl;
      else
        {
          cout << "Dorm: ";
          cin >> dorm;
          strncpy(room.dorm, dorm, sizeof(room.dorm));
          cout << "Number: ";
          cin >> room.number;
          while (! cin.eof() && cin.get() != '\n') ;

          #find first room using dorm, number;
          if (Netsim::status != Netsim::SUCCESS)
            cout << "No such room" << endl;
          else
            {
              #find student retaining occupiedBy;
              #connect student to occupiedBy;
              if (Netsim::status != Netsim::SUCCESS)
                Netsim::signal(false);
            }  
        }
    }
}

void removeStudentFromRoom()
{ // removes a student from room assigned to
  
  char name[20];

  cout << "Last: ";
  cin >> name;
  while (! cin.eof() && cin.get() != '\n') ;

  strncpy(student.lastName, name, sizeof(student.lastName));
  #find first student using lastName;
  if (Netsim::status != Netsim::SUCCESS)
    cout << "No such student" << endl;
  else
    {
      #get student;
      #if (! isMember occupiedBy)
        cout << "Not in any room" << endl;
      else
        {
          #disconnect student from occupiedBy;
          if (Netsim::status != Netsim::SUCCESS)
            Netsim::signal(false);
        }
    }
}

void changeRoom()
{ // Change a student from one room to another

  char name[20];
  char dorm[15];

  cout << "Last: ";
  cin >> name;
  while (! cin.eof() && cin.get() != '\n') ;

  strncpy(student.lastName, name, sizeof(student.lastName));
  #find first student using lastName;
  if (Netsim::status != Netsim::SUCCESS)
    cout << "No such student" << endl;
  else
    {
      #if (! isMember occupiedBy)
        cout << "Not in any room" << endl;
      else
        {
          #find owner within occupiedBy;
          #get room;
          cout << "Currently in: " << room.dorm << " " << room.number << endl;
          cout << "New dorm: ";
          cin >> dorm;
          strncpy(room.dorm, dorm, sizeof(room.dorm));
          cout << "New number: ";
          cin >> room.number;
          while (! cin.eof() && cin.get() != '\n') ;

          #find first room using dorm, number;
          if (Netsim::status != Netsim::SUCCESS)
            cout << "No such room" << endl;
          else
            {
              #find student retaining occupiedBy;
              #reconnect student within occupiedBy;
              if (Netsim::status != Netsim::SUCCESS)
                Netsim::signal(false);
            }  
        }
    }
}

void displayStudentRoom()
{ // Display the room of a specified student

  char name[20];

  cout << "Last name: ";
  cin >> name;
  while (! cin.eof() && cin.get() != '\n') ;

  strncpy(student.lastName, name, sizeof(student.lastName));
  #find first student using lastName;
  if (Netsim::status != Netsim::SUCCESS)
    cout << "No such student" << endl;
  else
    {
      #if (isMember occupiedBy)
        {
          #find owner within occupiedBy;
          #get room;
          cout << room.dorm << " " << room.number << endl;
        }
      else
        cout << "Not in any room" << endl;
    }
}

void displayRoomStudents()
{ // Display all students living in a given room

  char dorm[15];

  cout << "Dorm: ";
  cin >> dorm;
  cout << "Number: ";
  cin >> room.number;
  while (! cin.eof() && cin.get() != '\n') ;

  strncpy(room.dorm, dorm, sizeof(room.dorm));
  #find first room using dorm, number;
  if (Netsim::status != Netsim::SUCCESS)
    cout << "No such room" << endl;
  else 
    {
      #find first student within occupiedBy;
      if (Netsim::status != Netsim::SUCCESS)
        cout << "No students in this room" << endl;
      while (Netsim::status == Netsim::SUCCESS)
        {
          #get student;
          cout << student.lastName << " " << student.firstName << endl;
          #find next student within occupiedBy;
        }
    }
}

void displayAllStudents()
{ // Displays all students with their dorm assignments, if any

  #find first student;
  while (Netsim::status == Netsim::SUCCESS)
    {
      #keep using tempKeep;
      #get student;
      cout << student.lastName << " " << student.firstName << " " 
           << " arrived " << student.dateArrived << " gpa: " << student.gpa
           << endl; // date arrived as well
      #if (isMember occupiedBy)
        {
          #find owner within occupiedBy;
          #get room;
          cout << room.dorm << " " << room.number << endl;
        }
      else
        cout << "Not assigned" << endl;
      #find tempKeep;
      if (Netsim::status != Netsim::SUCCESS)
        Netsim::signal(false);
      cout << endl;
      #find next student;
    }
}

displayAllRooms()
{ // Displays all rooms, with count of occupants

  int count;

  #find first room;
  while (Netsim::status == Netsim::SUCCESS)
    {
      #get room;
      cout << room.dorm << " " << room.number << endl;
      count = 0;
      #find first student within occupiedBy;
      while (Netsim::status == Netsim::SUCCESS)
        {
          count += 1;
          #find next student within occupiedBy;
        }
      if (count == 0)
        cout << "No students assigned" << endl;
      else
        cout << count << " students assigned" << endl;
      cout << endl;
      #find next room;
    }
}

changeGPA()
{ // Prompts for a student name, then alters his GPA

  char name[20];

  cout << "Last name: ";
  cin >> name;
  while (! cin.eof() && cin.get() != '\n') ;

  strncpy(student.lastName, name, sizeof(student.lastName));
  #find first student using lastName;
  if (Netsim::status != Netsim::SUCCESS)
    cout << "No such student" << endl;
  else
    {
      #get student;
      cout << "Old GPA is " << student.gpa << ". Enter new gpa: "; 
      cin >> student.gpa;
      while (! cin.eof() && cin.get() != '\n') ;

      #modify student;
      if (Netsim::status != Netsim::SUCCESS)
        Netsim::signal(false);
   }
}

deleteAStudent()
{ // Prompts for a student name, then deletes him

  char name[20];

  cout << "Last name: ";
  cin >> name;
  while (! cin.eof() && cin.get() != '\n') ;

  strncpy(student.lastName, name, sizeof(student.lastName));
  #find first student using lastName;
  if (Netsim::status != Netsim::SUCCESS)
    cout << "No such student" << endl;
  else
    {
      #erase student;
      if (Netsim::status != Netsim::SUCCESS)
        Netsim::signal(false);
    }
}

deleteARoom()
{ // Prompts for a room, then deletes it 
 
  char dorm[15];

  cout << "Dorm: ";
  cin >> dorm;
  cout << "Number: ";
  cin >> room.number;
  while (! cin.eof() && cin.get() != '\n') ;

  strncpy(room.dorm, dorm, sizeof(room.dorm));
  #find first room using dorm, number;
  if (Netsim::status != Netsim::SUCCESS)
    cout << "No such room" << endl;
  else 
    {
      #erase room;
      if (Netsim::status != Netsim::SUCCESS)
        Netsim::signal(false);
    } 
}

debugger()
{ // This will be the call for the interactive debugger - will be done later

  Netsim::NETDbg();

}


main()
{
  int menuChoice;

  do 
    {
      menuChoice = menu();

      switch (menuChoice)
        {
          case  1: addStudent(); break;
          case  2: addRoom(); break;
          case  3: putStudentInRoom(); break;
          case  4: removeStudentFromRoom(); break;
          case  5: changeRoom(); break;
          case  6: displayStudentRoom(); break;
          case  7: displayRoomStudents(); break;
          case  8: displayAllStudents(); break;
          case  9: displayAllRooms(); break;
          case 10: changeGPA(); break;
          case 11: deleteAStudent(); break;
          case 12: deleteARoom(); break;
          case 13: debugger(); break;
        }
      if (menuChoice != 0)
        {
          cout << "Press Return to continue";
          while (! cin.eof() && cin.get() != '\n') ;
        }

    } while (menuChoice != 0);
}