#include "Course.h"

//---------------------------------------------------------------
// Constructor
//---------------------------------------------------------------
Course::Course(void) : limit(0), prereqs(0), semester(0), enrollment(0) {};
Course::Course(const Course& c) { *this = c; }
Course::Course(string cid,string n,string p,string i,string t,int l,int s,int e):
  id(cid),name(n),instructor(i),textbook(t), limit(l), semester(s), enrollment(e) {
  prereqs = 0;
  if(!p.empty()) setPrerequisites(p);
}

//---------------------------------------------------------------
// Assignment operator
//---------------------------------------------------------------
const Course& Course::operator=(const Course& c) {
  if (this == &c) return *this;
  
  id = c.getCourseNum();
  name = c.getName();
  instructor = c.getInstructor();
  textbook = c.getTextISBN();
  semester = c.getSemester();
  enrollment = c.getEnrollment();
  limit = c.getLimit();
  prereqs = c.getNumPrereqs();
  for(int i=0; i<prereqs; i++) {
    prereq[i] = c.getPrereq(i);
  }
  
  return *this;
}

//---------------------------------------------------------------
// Function returns the course number
//---------------------------------------------------------------
inline string Course::getCourseNum()   const { return id; }

//---------------------------------------------------------------
// Function returns the course name
//---------------------------------------------------------------
inline string Course::getName()        const { return name; }

//---------------------------------------------------------------
// Function returns the course instructor
//---------------------------------------------------------------
inline string Course::getInstructor()  const { return instructor; }

//---------------------------------------------------------------
// Function returns the ISBN number of the course text
//---------------------------------------------------------------
inline string Course::getTextISBN()    const { return textbook; }

//---------------------------------------------------------------
// Function returns the course semester
//---------------------------------------------------------------
inline int    Course::getSemester()    const { return semester; }

//---------------------------------------------------------------
// Function returns the current number of students registered
//---------------------------------------------------------------
inline int  Course::getEnrollment()  const { return enrollment; }

//---------------------------------------------------------------
// Function returns the course enrollment limit
//---------------------------------------------------------------
inline int  Course::getLimit()       const { return limit; }

//---------------------------------------------------------------
// Function returns prereq i for course
//---------------------------------------------------------------
inline string Course::getPrereq(int i) const { return prereq[i]; }

//---------------------------------------------------------------
// Function returns the total number of prereqs
//---------------------------------------------------------------
inline int Course::getNumPrereqs()  const { return prereqs; }

//---------------------------------------------------------------
// Function parses a CSV string representing the course 
// prerequisites and 
//---------------------------------------------------------------
void Course::setPrerequisites(string a) {
  int i=0;
  Tokenizer t(a,',');
  while(t.hasMoreTokens()) {
    prereq[++i] = t.getToken();
    t++;
  }
  prereqs = i;
}

//---------------------------------------------------------------
// Function returns true if course has prerequisites
//---------------------------------------------------------------
bool Course::hasPrereqs(void) {
  return( prereqs > 0 );
}

//---------------------------------------------------------------
// Function performs a test and set operation on the enrollment 
// number; If course is open, then increment the number enrolled 
// and return true; otherwise, return false;
//---------------------------------------------------------------
inline bool Course::isOpen() {
  if( enrollment >= limit ) return false;
  
  enrollment++;
  return true;
}

//---------------------------------------------------------------
// Function sets the textbook
//---------------------------------------------------------------
inline void Course::setTextbook(string isbn) {
  textbook = isbn;
}


/************ I n p u t   F u n c t i o n ***************/
istream& operator>> (istream& in, Course& c)
{
  char* input = new char[50];
  string temp;

  // Input course number
  cout << "Course Number [" << c.id << "] : ";
  in.get(input,7,'\n');
  in.ignore();
  temp = input;
  if( temp.length() > 0 ) c.id = temp;

  // Input course name
  cout << "Course [" << c.name <<"] : "; 
  in.get(input,50,'\n');
  in.ignore();
  temp = input;
  if( temp.length() > 0 ) c.name = temp;

  // Input prerequisities
  do { 
    cout << "Number of Prerequisities: "; cin >> c.prereqs;
    in.ignore();
    if( c.prereqs > 5 ) {
      cout << "Please enter up to five prereqs" << endl;
      c.prereqs = 5;
    }
  } while( c.prereqs < 0 );

  for(int i=0; i<c.prereqs; i++) {
    cout << "Prerequisite No. "<<i<<" ["<<c.prereq[i]<<"] : ";
    in.get(input,50,'\n');
    in.ignore();
    temp = input;
    if( temp.length() > 0 ) c.prereq[i] = temp;
  }

  // Input instructor
  cout << "Instructor [" << c.instructor << "] : ";
  in.get(input,50,'\n');
  in.ignore();
  temp = input;
  if( temp.length() == 10 ) c.instructor = temp;

  // Input course limit
  cout << "Enrollment Limit [" << c.limit << "] : ";
  in.get(input,7,'\n');
  in.ignore();
  temp = input;
  if( temp.length() > 0 ) c.limit = atoi(temp.c_str());

  // Input semester
  cout << "Semester [" << c.semester << "] : ";
  cin.get(input,5,'\n');
  in.ignore();
  temp = input;
  if( temp.length() > 0 ) c.semester = atoi(temp.c_str());

  return in;
}

/************ O u t p u t   F u n c t i o n ***************/
ostream& operator<< (ostream& out, Course& c)
{
  out << "C o u r s e" << endl;
  out << "Number: " << c.id << endl;
  out << "Name: " << c.name << endl;
  for(int i=0; i<c.prereqs; i++)
    cout << "   Prereq No. " <<i<<" : "<<c.prereq[i]<< endl;
  out << "Textbook ISBN: " << c.textbook <<endl;
  out << "Enrollment Limit: " << c.limit << endl;
  out << "Number of Students Enrolled: " << c.enrollment << endl;

  return out;
}


bool Course::operator== (const Course& c) {
  return( id == c.getCourseNum() );
}

bool Course::operator!= (const Course& c) {
  return( id != c.getCourseNum() );
}

//---------------------------------------------------------------
// Convert a course object into a string delimeted by the 
// ':' character.  This is a useful function for the File 
// operations, which write lines to files.
//---------------------------------------------------------------
string Course::toString(void)
{
  char* buf = new char[50];

  // Turn ID and Name into a string
  //sprintf(buf,"%d:%s:",id,name.c_str());
  string s = id+":"+name+":";

  // Create CSV list of prereqs and append
  for(int i=0; i<prereqs; i++) {
    s += prereq[i];
    if(i!=prereqs-1) s += ",";
  }

  // Append instructor and textbook isbn
  s += (":" + instructor + ":" + textbook + ":");

  sprintf(buf,"%d:%d:%d",limit,semester,enrollment);
  string s2(buf);
  s += s2;
  return s;
}

//---------------------------------------------------------------
// Convert a ':' delimeted string to a Course object; 
// This is a useful function for the File operations which 
// read lines from files.
//---------------------------------------------------------------
Course Course::parse(string s)
{
  Tokenizer t(s,':');
  return( Course
	  (t.getToken(0),
	   t.getToken(1),
	   t.getToken(2),
	   t.getToken(3),
	   t.getToken(4),
	   atoi(t.getToken(5).c_str()),
	   atoi(t.getToken(6).c_str()),
	   atoi(t.getToken(7).c_str())));
}
