// Project 2, step 1  p2s1.cpp
// 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

#include <cstdlib> // for atoi

#include <cstring> // for strncpy


struct Team
{
  char domainName[shortStringLen];
  char fullName[longStringLen];
  char mascot[longStringLen];
  char city[shortStringLen];
  char state[3]; // 2 for abbreviation, + 1 for \0
  int foundingYear;
  Team *next;
};

#include <new>

char promptForOption();

// function prototypes

void addTeamToList(Team **teamListHeadPtr, Team **teamListTailPtr);
void deleteTeamFromList(Team **teamListHeadPtr, Team **teamListTailPtr);
void insertTeamAtTail(Team *p, Team **teamListHeadPtr, Team **teamListTailPtr);
void printSummary(Team *teamListHead);
void quitProgram();
void listTeams(Team *teamListHead);
void updateTeamInfo(Team *teamListHead);
void printErrorMessage();
void printTeamHeaders();
void printTeam(Team *p);
void findTeam(Team *p);
void printMenu();


int main(void)
{
  Team *teamListHead;
  Team *teamListTail;
  
  // initialize empty list

  teamListHead = teamListTail = NULL;
  
  char option;

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

      switch (option)
	{
	case 'a':
	  addTeamToList(&teamListHead, &teamListTail);
	  break;
	case 'd':
	  deleteTeamFromList(&teamListHead, &teamListTail);
	  break;
	case 'f':
	  findTeam(teamListHead);
	  break;
	case 's':
	  printSummary(teamListHead);
	  break;
	case 'q':
	  quitProgram();
	  break;
	case 'l':
	  listTeams(teamListHead);
	  break;
	case 'u':
	  updateTeamInfo(teamListHead);
	  break;
	default:
	  printErrorMessage();
	}
    }
  return 0;
}

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

char promptForOption(void)
{
  char option;
  printMenu();
  cout << "Enter option > " << flush;
  cin >> option;
  cin.ignore(80,'\n'); // ignore all remaining characters on the line
  return option;
}


void findTeam(Team *teamListHead)
{
  char key[shortStringLen]; // key is the team we are searching for

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

  int headersPrinted = 0;

  for (p=teamListHead; p!=NULL ; p=p->next)
    {
      if (strcmp(p->domainName,key)==0) // key matches
	{
	  if (!headersPrinted)
	    {
	      printTeamHeaders();
	      headersPrinted = 1;
	    }
	  printTeam(p);      
	} // if key matches
    } // end for   
  
}


void deleteTeamFromList(Team **teamListHeadPtr, Team **teamListTailPtr)
{
  char key[shortStringLen]; // key is the team we are searching for

  cout << "Enter domain name to search for > " << flush;
  cin.getline(key,shortStringLen,'\n');
  
  Team *p;
  Team *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=(*teamListHeadPtr); p!=NULL ; trailp = p, p=p->next)
    {
      if (strcmp(p->domainName,key)==0) // key matches
	{
	  cout << "Deleting this element: " << endl;
	  printTeamHeaders();
	  printTeam(p);      

	  if (trailp == NULL) 	      // we are deleting the head element
	    (*teamListHeadPtr) = p->next;
	  else
	    trailp->next = p->next; // make the prev element point past p

	  if (p==(*teamListTailPtr)) // we are deleting the tail  
	    (*teamListTailPtr) = trailp; // update the tail

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

void addTeamToList(Team **teamListHeadPtr, Team **teamListTailPtr)
{
  Team *p;

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

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

  cout << " Enter full school name > " << flush;
  cin.getline(p->fullName,longStringLen,'\n');
  p->fullName[longStringLen-1] = '\0';

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

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

  char stateString[shortStringLen];
  cout << " Enter state > " << flush;
  cin.getline(stateString,shortStringLen,'\n');
  strncpy(p->state,stateString,3);
  p->state[2]= '\0';

  char foundingYearString[shortStringLen];
  cout << " Enter founding year> " << flush;
  cin.getline(foundingYearString,shortStringLen,'\n');
  p->foundingYear=atoi(foundingYearString);
  
  p->next = NULL;
  
  insertTeamAtTail(p, teamListHeadPtr, teamListTailPtr);

}

void updateTeamInfo(Team *teamListHead)
{
  char key[shortStringLen]; // key is the team we are searching for

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

  int headersPrinted = 0;


  for (p=teamListHead; p!=NULL ; p=p->next)
    {
      if (strcmp(p->domainName,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 domain name > " << p->domainName << endl;
	  cout << " New value > " << flush;
	  cin.getline(shortString,shortStringLen,'\n');
	  shortString[shortStringLen-1] = '\0';
	  if (strcmp(shortString,"")!=0)
	    {
	      strncpy(p->domainName,shortString,shortStringLen);
	    }

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

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

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

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

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

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



void insertTeamAtTail(Team *p, Team **teamListHeadPtr, Team **teamListTailPtr)
{
  if ((*teamListHeadPtr)==NULL) // if this is the first element in list
    {
      (*teamListHeadPtr)=p;
    }
  else // link last element in list to this new element
    {
      (*teamListTailPtr)->next = p;
    }
  (*teamListTailPtr) = p; // make p the new tail
}

void printSummary(Team *teamListHead)
{
  int count=0;
  Team *p;
  for (p=teamListHead; p; p=p->next)
    count++;

  cout << "There are " << count << " teams in the list. " << endl;

}

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

void listTeams(Team *teamListHead)
{
  Team *p;
  printTeamHeaders();
  for (p=teamListHead; p; p=p->next)
    printTeam(p);

}

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


void printTeamHeaders()
{

  cout << setw(12) << "Domain"
       << setw(25) << "Full Name"
       << setw(15) << "Mascot"
       << setw(15) << "City"
       << setw(3)  << "St"
       << setw(5 ) << "Year"  << endl;

  cout << setw(12) << "======"
       << setw(25) << "========="
       << setw(15) << "======"
       << setw(15) << "===="
       << setw(3)  << "=="
       << setw(5 ) << "===="  << endl;

}


void printTeam(Team *p)
{
  cout << setw(12) << p->domainName
       << setw(25) << p->fullName
       << setw(15) << p->mascot
       << setw(15) << p->city
       << setw(3)  << p->state
       << setw(5 ) << p->foundingYear << endl;
}


