/* proj2stage4.c  P. Conrad CISC105  Fall 2005 */
/* Example to follow for stage 4 of project 2;
   illustrates adding a calculation */

#include <stdio.h>
#include <string.h> /* for strtok, strncpy */
#include <stdlib.h> /* for atof() */

#define HIKING_TRAIL_NAME_LEN 30 /* max length of hiking trail name */
#define FILENAME_LEN 128  /* maximum length of filename */
#define MAXLINE 1024 /* maximum length of input line in file */

#define MAX_HIKING_TRAILS 10  /* no more than 10 hiking trails */

/* function prototypes */

char readOneChar(void);
void printPrompt(void);


int  readFileIntoParallelArrays
(char hikingTrailNames[MAX_HIKING_TRAILS][HIKING_TRAIL_NAME_LEN],
 double *hikingTrailLengthsInMiles);


void printHelp(void);

/* Ask about this "const" in lecture */


void   printValues
(const char hikingTrailName[MAX_HIKING_TRAILS][HIKING_TRAIL_NAME_LEN],
 const double *hikingTrailLengthsInMiles,
 int count);

/* $$$ new function prototypes for the new functions */

void printShortestTrails
(const char hikingTrailNames[MAX_HIKING_TRAILS][HIKING_TRAIL_NAME_LEN],
 const double *hikingTrailLengthsInMiles,
 const int count);


double lengthOfShortestTrail  (const double *hikingTrailLengthsInMiles, 
			       const int  numTrails);


/***************** MAIN PROGRAM **************/


int main(void)
{
  /* declare variables */


  char hikingTrailNames[MAX_HIKING_TRAILS][HIKING_TRAIL_NAME_LEN];
  double hikingTrailLengthsInMiles[MAX_HIKING_TRAILS];

  int numTrails = 0;  

  char c; /* menu option */
  
  /* main menu */

  printPrompt();
  c = readOneChar();
  while (c!='q' && c!='Q')  /* while user didn't select quit */
    {
      switch(c)
	{
	case 'h':
	case 'H':
	  printHelp();
	  break;

	case 'r':
	case 'R':
	  /* read one line from the file and store the result
	     into the array of strings hikingTrailNames, and the
	     array of doubles hikingTrailLengthsInMiles  

	     Note that since both of these are arrays, no & is needed!*/
	  

	  numTrails = readFileIntoParallelArrays(hikingTrailNames,
						 hikingTrailLengthsInMiles);




	  break;

	  /* $$$ we add a new m option to the menu */
	case 'm':
	case 'M': /* shortest trail in the bunch */
	  {
	    printShortestTrails(hikingTrailNames,
				hikingTrailLengthsInMiles, 
				numTrails);
	  }
	  
	  break; /*$$$ in lecture, show what happens if you remove this! */
	    
	case 'p':
	case 'P': /* print out the trails */


	  printValues(hikingTrailNames,
		      hikingTrailLengthsInMiles, 
		      numTrails);
	  break;
	    
	default:
	  printf("I don't understand the option: %c\n",c);
	  break;
	  
	}
      printPrompt();
      c = readOneChar();

    } /* end while */

  printf("Thanks for using this program.\n");
  printf("Bye now.\n");

}




void printHelp(void)
{
  printf("\n");
  printf(" h: help\n");
  printf(" m: minimum value (shortest trails)\n"); /* $$$ add to help */
  printf(" p: print values\n");
  printf(" q: quit\n");
  printf(" r: read values\n");
  printf("\n");

}

void printPrompt(void)
{
  printf("Enter option (type h for help): ");
}

char readOneChar(void)
{
  char c;
  fflush(stdin);
  scanf("%c",&c);
  return c;
}



int  readFileIntoParallelArrays
(char hikingTrailNames[MAX_HIKING_TRAILS][HIKING_TRAIL_NAME_LEN],
 double *hikingTrailLengthsInMiles)
{
  
  char filename[FILENAME_LEN];
  char inputLine[MAXLINE];
  FILE *infile;

  char *result; /* for result of fgets */

  char *hikingTrailNamePtr;
  char *hikingTrailLengthPtr;

  int count; /* number of records that were read from the file */

  printf("Please enter a filename: ");
  fflush(stdin);
  scanf("%s",&filename); /* &filename is redundant;ask about this in lecture!*/
  
  infile = fopen(filename, "r");

  /* check whether file opened properly */

  if (infile == NULL)
    {
      perror(filename);
      fprintf(stderr,"Can't open %s\n", filename);
      
      /* set the values to empty string, and zero */

      fclose(infile); /* close the input file */
      return 0; /* We have to return 0 so we know we read zero trails */
 
    }

  count = 0;

  /* read until end of file  */ 

  result = fgets(inputLine, MAXLINE, infile);
  
  while (result != NULL)
    {
  
      /* divide up the string at the commas;
	 requires #include <string.h>.  Ask about this in lecture */
      
      hikingTrailNamePtr = strtok(inputLine,",");
      hikingTrailLengthPtr = strtok(NULL,",");
      
      /* store the results in the arrays first, THEN increment count*/
      /* always do it in THAT order! */
      
      strncpy(hikingTrailNames[count],hikingTrailNamePtr,
	      HIKING_TRAIL_NAME_LEN);
      hikingTrailLengthsInMiles[count] = atof(hikingTrailLengthPtr);
      
      count++;

      /* try to read the next line of data */
      result = fgets(inputLine, MAXLINE, infile);
    }
     

  printf("Data read successfully from file\n");
  
  /* close the input file */
  
  fclose(infile);
  
  /* return the number of lines that you read */

  return count; /* return the number of trails read */
  
}



void   printValues
(const char hikingTrailNames[MAX_HIKING_TRAILS][HIKING_TRAIL_NAME_LEN],
 const double *hikingTrailLengthsInMiles,
 const int count)
{
  int i;
  for (i=0; i<count; i++)
    {
      printf("\n");
      printf("  hiking trail name: %s\n",hikingTrailNames[i]);
      printf("    length in miles: %6.1lf miles\n",
	     hikingTrailLengthsInMiles[i]);
      printf("\n");
    }
}

/* $$$ Read the printShortestTrail function carefully; it is subtle. */
   

/* find the length of the shortest trail first, then
   print ALL trails that match that length */

void printShortestTrails
(const char hikingTrailNames[MAX_HIKING_TRAILS][HIKING_TRAIL_NAME_LEN],
 const double *hikingTrailLengthsInMiles,
 const int count)
{
  
  int i;
  
  double lengthOfShortest;
  if (count == 0)
    {
      printf("No trails to search.. try r command first!\n");
      return;
    }
      
  lengthOfShortest = lengthOfShortestTrail  (hikingTrailLengthsInMiles, 
					     count);

  /* print ALL trails that have the shortest length;
     even if there are ties! */

  for (i=0; i<count; i++)
    {
      if (hikingTrailLengthsInMiles[i] == lengthOfShortest)
	{
	  printf("\n");
	  printf("  hiking trail name: %s\n",hikingTrailNames[i]);
	  printf("    length in miles: %6.1lf miles\n",
		 hikingTrailLengthsInMiles[i]);
	  printf("\n");
	}
    }

  return; /* statement not strictly needed, but good style */
}


/* $$$ this is a new helper function that factors out the searching part */

/* Find the length of the shortest trail(s) */

double lengthOfShortestTrail  (const double *hikingTrailLengthsInMiles, 
				const int  numTrails)
{

  int i;
  int lengthOfShortestTrail;

  /* defensive programming: make sure we didn't get called on an empty file */

  if (numTrails == 0)
    {
      fprintf(stderr,"Something went wrong in file %s line %d\n",
	      __FILE__, __LINE__);
      exit(1);
    }
  
  /* initialize to first element in array */

  lengthOfShortestTrail = hikingTrailLengthsInMiles[0];


  /* if any other element of array is smaller, make THAT one
     the smallest */

  for (i=1; i<numTrails; i++)
    {
      if (hikingTrailLengthsInMiles[i] < lengthOfShortestTrail)
	lengthOfShortestTrail = hikingTrailLengthsInMiles[i];
    }

  return lengthOfShortestTrail;
  
}




