// Example code to help with Project 2
// code to make a linked list of movies...
// P. Conrad, Spring 2004

#include <iostream>

using std::endl;
using std::cout;
using std::cin;
using std::cerr;
using std::flush;
using std::ws;

#include <iomanip>
using std::setw;

const int shortStringLen = 31; // can hold only 20 chars, + 1 for \0
const int longStringLen = 51; // can hold only 40 chars, + 1 for \0
const int inputLineLen = 81; // can hold 80 chars, +1 for \0
const int ratingLen = 6; // can hold 5 chars, +1 for \0

#include <cstdlib> // for atoi

#include <cstring> // for strncpy


struct Movie
{
  char movieName[longStringLen];
  char movieStar[longStringLen];
  char rating[ratingLen]; 
  int numStars; 
  Movie *next;
};

#include <new>

char promptForOption();

// function prototypes

void addMovieToList(Movie **movieListHeadPtr, Movie **movieListTailPtr);
void deleteMovieFromList(Movie **movieListHeadPtr, Movie **movieListTailPtr);
void insertMovieAtTail(Movie *p, Movie **movieListHeadPtr, Movie **movieListTailPtr);
void printSummary(Movie *movieListHead);
void quitProgram();
void listMovies(Movie *movieListHead);
void updateMovieInfo(Movie *movieListHead);
void printErrorMessage();
void printMovieHeaders();
void printMovie(Movie *p);
void findMovie(Movie *p);
void printMenu();


int main(void)
{
  Movie *movieListHead;
  Movie *movieListTail;
  
  // initialize empty list

  movieListHead = movieListTail = NULL;
  
  char option;

  while (1) // infinite loop; get out via exit(-1) inside quitProgram();
    {
      option = promptForOption();

      switch (option)
	{
	case 'a':
	  addMovieToList(&movieListHead, &movieListTail);
	  break;
	case 'd':
	  deleteMovieFromList(&movieListHead, &movieListTail);
	  break;
	case 'f':
	  findMovie(movieListHead);
	  break;
	case 's':
	  printSummary(movieListHead);
	  break;
	case 'u':
	  updateMovieInfo(movieListHead);
	  break;
	case 'q':
	  quitProgram();
	  break;
	case 'l':
	  listMovies(movieListHead);
	  break;
	default:
	  printErrorMessage();
	}
    }
  return 0;
}

void printMenu()
{
  cout << endl
       << " Main Menu: " << endl
       << "    a: add movie to list " << endl
       << "    d: delete movie " << endl
       << "    f: find movie " << endl
       << "    l: list movies " << endl
       << "    u: update movies " << endl
       << "    q: quit program   " << endl
       << "    s: summarize list  " << endl
       << endl;
}

char promptForOption(void)
{
  char inputLine[shortStringLen];
  printMenu();
  cout << "Enter option > " << flush;
  cin.getline(inputLine,shortStringLen,'\n');
  return inputLine[0];
}


void findMovie(Movie *movieListHead)
{
  char key[shortStringLen]; // key is the movie we are searching for

  cout << "Enter movie name to search for > " << flush;
  cin.getline(key,shortStringLen,'\n');
  
  Movie *p;

  int headersPrinted = 0;

  for (p=movieListHead; p!=NULL ; p=p->next)
    {
      if (strcmp(p->movieName,key)==0) // key matches
	{
	  if (!headersPrinted)
	    {
	      printMovieHeaders();
	      headersPrinted = 1;
	    }
	  printMovie(p);      
	} // if key matches
    } // end for   
  
}


void deleteMovieFromList(Movie **movieListHeadPtr, Movie **movieListTailPtr)
{
  char key[shortStringLen]; // key is the movie we are searching for

  cout << "Enter movie name to search for > " << flush;
  cin.getline(key,shortStringLen,'\n');
  
  Movie *p;
  Movie *trailp;

  int headersPrinted = 0;

  // trailp should "trail" the pointer p, and be the
  // pointer to the element _before_ the matching one

  trailp = NULL;

  for (p=(*movieListHeadPtr); p!=NULL ; trailp = p, p=p->next)
    {
      if (strcmp(p->movieName,key)==0) // key matches
	{
	  cout << "Deleting this element: " << endl;
	  cout << "Only, I don't know how yet!!! Help me!!! " <<  endl;
	  // put the code 

	  return ;

	  break;
	} // if key matches
      
    } // end for   
  
}

void addMovieToList(Movie **movieListHeadPtr, Movie **movieListTailPtr)
{
  Movie *p;

  p = new Movie;
  cout << "Adding a new node: " << endl;

  cout << " Enter movie name > " << flush;
  cin.getline(p->movieName,shortStringLen,'\n');
  p->movieName[shortStringLen-1] = '\0';

  cout << " Enter movie star > " << flush;
  cin.getline(p->movieStar,longStringLen,'\n');
  p->movieStar[longStringLen-1] = '\0';

  cout << " Enter rating > " << flush;
  cin.getline(p->rating,ratingLen,'\n');
  p->rating[ratingLen-1] = '\0';

  char numStarsString[shortStringLen];
  cout << " Enter number of stars> " << flush;
  cin.getline(numStarsString,shortStringLen,'\n');
  p->numStars=atoi(numStarsString);
  
  p->next = NULL;
  
  insertMovieAtTail(p, movieListHeadPtr, movieListTailPtr);

}

void updateMovieInfo(Movie *movieListHead)
{
  char key[shortStringLen]; // key is the movie we are searching for

  cout << "Enter movie name to search for > " << flush;
  cin.getline(key,shortStringLen,'\n');
  
  Movie *p;

  int headersPrinted = 0;


  for (p=movieListHead; p!=NULL ; p=p->next)
    {
      if (strcmp(p->movieName,key)==0) // key matches
	{
	  char shortString[shortStringLen];
	  char longString[longStringLen];

	  cout << "Enter a blank line to keep old value for any item. "<< endl;
	  cout << endl;

	  cout << " Current value of movie name > " << p->movieName << endl;
	  cout << " New value > " << flush;
	  cin.getline(shortString,shortStringLen,'\n');
	  shortString[shortStringLen-1] = '\0';
	  if (strcmp(shortString,"")!=0)
	    {
	      strncpy(p->movieName,shortString,shortStringLen);
	    }

	  cout << " Current value of movie star > " << p->movieStar << endl;
	  cout << " New value > " << flush;
	  cin.getline(longString,longStringLen,'\n');
	  longString[longStringLen-1] = '\0';
	  if (strcmp(longString,"")!=0)
	    {
	      strncpy(p->movieStar,longString,longStringLen);
	    }


	  cout << " Current value of rating > " << p->rating << endl;
	  cout << " New value > " << flush;
	  cin.getline(shortString,ratingLen,'\n');
	  shortString[ratingLen-1]='\0';
	  if (strcmp(shortString,"")!=0)
	    {
	      strncpy(p->rating,shortString,ratingLen);
	    }

	  cout << " Current value of numStars > " << p->numStars 
	       << endl;
	  cout << " New value > " << flush;
	  cin.getline(shortString,shortStringLen,'\n');
	  shortString[shortStringLen-1] = '\0';
	  if (strcmp(shortString,"")!=0)
	    {
	      p->numStars = atoi(shortString);
	    }

	  cout << "Here are the updated values: " << endl;

	  printMovie(p);      
	} // if key matches
    } // end for   
  
}



void insertMovieAtTail(Movie *p, Movie **movieListHeadPtr, Movie **movieListTailPtr)
{

  if ((*movieListHeadPtr)==NULL) // if this is the first element in list
    {
      (*movieListHeadPtr)=p;
    }
  else // link last element in list to this new element
    {
      (*movieListTailPtr)->next = p;
    }
  (*movieListTailPtr) = p; // make p the new tail


}

void printSummary(Movie *movieListHead)
{
  int count=0;

  cout << "This option not implemented yet... you figure it out!!!" << endl;
  // figure out here how to assign a value to count that is equal to
  // the number of movies in the list
  //cout << "There are " << count << " movies in the list. " << endl;

}

void quitProgram()
{
  cout << "Thanks for using this program " << endl;
  exit(-1);
}

void listMovies(Movie *movieListHead)
{
  Movie *p;
  printMovieHeaders();
  for (p=movieListHead; p; p=p->next)
    printMovie(p);

}

void printErrorMessage()
{
  cout << "That option was not understood; please try again" << endl;
}


void printMovieHeaders()
{

  cout << setw(12) << "Movie"
       << setw(25) << "Starring"
       << setw(ratingLen)  << "Rated"
       << setw(10 ) << "Stars"  << endl;

  cout << setw(12) << "======"
       << setw(25) << "========"
       << setw(ratingLen)  << "=="
       << setw(10) << "====="  << endl;

}


void printMovie(Movie *p)
{
  cout << setw(12) << p->movieName
       << setw(25) << p->movieStar
       << setw(ratingLen)  << p->rating
       << setw(5 ) << p->numStars << endl;
}


