/*********************************************************************
 * Author: B. Alex Bridges                                           *
 * Login ID: brid0129                                                *
 * Class: CPSC-102, Summer 1998                                      *
 * Project: Programming Assignment 4                                 *
 * Description: This program is a simple database query system for a *
 *              video store.                                         *
 * Contents: Methods for program actions--search and list.           *
 *********************************************************************/

/* IMPORTS */
import java.io.*;


class Database
{
	/* CONSTANTS */
	final static boolean b_debug = false;	// CONTROLS EXTRA DEBUG OUTPUT

	/* GLOBAL VARIABLES */
	public static Videos Videos_in;			// BINARY SEARCH TREE VIDEO OBJECT FOR IN STOCK MOVIES
	public static Videos Videos_out;		// BINARY SEARCH TREE VIDEO OBJECT FOR CHECKED OUT MOVIES

	/*************************************************************************
	 * Method: check_db                                                      *
	 * Purpose: Checks for the existence of the video database file.         *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'str_database' = The filename of the video database.        *
	 * Output: --RETURNS--                                                   *
	 *         => true  = The file exists.                                   *
	 *         => false = The file does NOT exist.                           *
	 *************************************************************************/
	public static boolean check_db(String str_database)
	{
		/* LOCAL VARIABLES */
		FileReader fr_temp;		// TEMPORARY FILE READER

		try
		{
			/* CHECK FOR FILE'S EXISTENCE */
			fr_temp = new FileReader(str_database);

			return true;
		} // try
		/* EXCEPTION HANDLING */
		catch(FileNotFoundException exception)
		{
			return false;
		} // catch
	} // method check_db

	/*************************************************************************
	 * Method: read_db                                                       *
	 * Purpose: Reads the video database, storing contents into the          *
	 *          appropriate binary search tree.                              *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'str_database' = The filename of the video database.        *
	 * Output: --EXIT VALUE--                                                *
	 *         => FATAL EXCEPTION = -1                                       *
	 *************************************************************************/
	public static void read_db(String str_database)
	{
		/* LOCAL VARIABLES */
		Video Video_current;		// VIDEO OBJECT FOR CURRENT MOVIE

		try
		{
			/* INITIALIZE BINARY SEARCH TREES */
			Videos_in = new Videos();
			Videos_out = new Videos();

			/* FILE INPUT STREAM SETUP FOR DATABASE */
			BufferedReader br_file_in = new BufferedReader( new FileReader(str_database) );

			System.out.println(" Reading the video database '"+str_database+"' . . . ");

			/* LIST BASED ON SELECTED AVAILABILITY */
			while( br_file_in.ready() )
			{
				Video_current = new Video();
				Video_current = Videos.get_movie(br_file_in);

				if( Video_current.str_available.equals("true") )
					Videos_in.insert_movie(Video_current);
				else if( Video_current.str_available.equals("false") )
					Videos_out.insert_movie(Video_current);
			} // while

			System.out.println(" Read completed.\n");
		} // try
		/* EXCEPTION HANDLING */
		catch(IOException exception)
		{
			System.out.println(" FATAL EXCEPTION: File input problem.");
			System.exit(-1);
		} // catch
	} // method read_db

	/*************************************************************************
	 * Method: availability                                                  *
	 * Purpose: Modifies the availability of a given movie.                  *
	 * Input: --PARAMATERS--                                                 *
 	 *        => 'str_given'      = The title for which to modify.           *
	 *        => 'b_availability' = The expected availability.               *
	 * Output: none                                                          *
	 *************************************************************************/
	public static void availability(String str_given, boolean b_availability)
	{
		/* LOCAL VARIABLES */
		Video Video_in_result;		// VIDEOS OBJECT FOR RESULT MOVIE FROM IN STOCK B.S.T.
		Video Video_out_result;		// VIDEOS OBJECT FOR RESULT MOVIE FROM CHECKED OUT B.S.T.
		boolean b_in;				// BOOLEAN FOR EXISTENCE OF MOVIE AS IN STOCK VIDEO
		boolean b_out;				// BOOLEAN FOR EXISTENCE OF MOVIE AS CHECKED OUT VIDEO

		/* VERIFY EXISTENCE */
		System.out.println(" Verifying existence of '"+str_given+"' . . . ");

		// => IN STOCK LINKED LIST
		Video_in_result = Videos_in.find_movie(str_given);

		if(Video_in_result != null)
			b_in = true;
		else
			b_in = false;

		// => CHECKED OUT LINKED LIST
		Video_out_result = Videos_out.find_movie(str_given);

		if(Video_out_result != null)
			b_out = true;
		else
			b_out = false;

		// => RESULTS
		if(!b_in && !b_out)
		{
			System.out.println(" ERROR: The title '"+str_given+"' is NOT carried.\n"+
			                   " End of verifying existence.\n");
			return;
		} // if
		else
		{
			System.out.println(" The title '"+str_given+"' is carried.\n"+
			                   " End of verifying existence.\n");
		} // else

		/* VERIFY STATUS */
		System.out.println(" Verifying status of '"+str_given+"' . . . ");

		// => RETURNING VIDEO, BUT ALREADY IN STOCK
		if(b_availability && b_in)
		{
			System.out.println(" ERROR: The title '"+str_given+"' is already in stock.\n"+
			                   " End of verifying status.\n");
			return;
		} // if
		// => CHECKING OUT VIDEO, BUT ALREADY CHECKED OUT
		else if (!b_availability && b_out)
		{
			System.out.println(" ERROR: The title '"+str_given+"' is already checked out.\n"+
			                   " End of verifying status.\n");
			return;
		} // if
		// => RETURNING VIDEO WHICH IS CHECKED OUT
		else if(b_availability && !b_in && b_out)
		{
			System.out.println(" The title '"+str_given+"' can be returned.\n"+
			                   " End of verifying status.\n");
		} // if
		// => CHECKING OUT VIDEO WHICH IS IN STOCK
		else if(!b_availability && b_in && !b_out)
		{
			System.out.println(" The title '"+str_given+"' can be checked out.\n"+
			                   " End of verifying status.\n");
		} // if
		else
			System.out.println(" ERROR: This case is NOT currently handled.\n"+
			                   "  -> Availibility = '"+b_availability+"'\n"+
   			                   "  -> In Stock     = '"+b_in+"'\n"+
   			                   "  -> Checked Out  = '"+b_out+"'\n"+
							   "\n"+
			                   " End of verifying status.\n");

		/* CHECK OUTS */
		if(!b_availability)
		{
			System.out.println(" Checking out the title '"+str_given+"' . . . ");

			// => DELETE FROM IN STOCK LINKED LIST
			Videos_in.delete_movie(str_given);

			// => ADJUST RESULT'S AVAILABILITY ACCORDINGLY
			Video_in_result.str_available = "false";

			// => INSERT INTO CHECKED OUT LINKED LIST
			Video_in_result.Video_left = null; // DROP REMAINING LEFT HALF OF B.S.T.
			Video_in_result.Video_right = null; // DROP REMAINING RIGHT HALF OF B.S.T.
			Videos_out.insert_movie(Video_in_result);

			System.out.println(" Done checking out.\n");
		} // if
		/* RETURNS */
		else
		{
			System.out.println(" Returning the title '"+str_given+"' . . . ");

			// => DELETE FROM CHECKED OUT LINKED LIST
			Videos_out.delete_movie(str_given);

			// => ADJUST RESULT'S AVAILABILITY ACCORDINGLY
			Video_out_result.str_available = "true";

			// => INSERT INTO IN STOCK LINKED LIST
			Video_out_result.Video_left = null; // DROP REMAINING LEFT HALF OF B.S.T.
			Video_out_result.Video_right = null; // DROP REMAINING RIGHT HALF OF B.S.T.
			Videos_in.insert_movie(Video_out_result);

			System.out.println(" Done returning.\n");
		} // else
	} // method availability

	/*************************************************************************
	 * Method: search                                                        *
	 * Purpose: Searches both binary search trees for a matching title.      *
	 * Input: --PARAMATERS--                                                 *
 	 *        => 'str_given'   = The title for which to search.              *
	 * Output: --EXIT VALUE--                                                *
	 *         => FATAL EXCEPTION = -1                                       *
	 *************************************************************************/
	public static void search(String str_given)
	{
		/* LOCAL VARIABLES */
		Video Video_found;	// VIDEOS OBJECT FOR RESULT MOVIE

		System.out.println(" Searching for '"+str_given+"' . . . ");

		/* IN STOCK LINKED LIST */
		Video_found = Videos_in.find_movie(str_given);
		if(Video_found != null)
		{
			System.out.println(" The title '"+str_given+"' was found to be in stock.\n");
			Videos.print_movie(Video_found);
		} // if
		else
			System.out.println(" The title '"+str_given+"' was NOT found to be in stock.");

		/* CHECKED OUT LINKED LIST */
		Video_found = Videos_out.find_movie(str_given);
		if(Video_found != null)
		{
			System.out.println(" The title '"+str_given+"' was found to be checked out.\n");
			Videos.print_movie(Video_found);
		} // if
		else
			System.out.println(" The title '"+str_given+"' was NOT found to be checked out.");

		System.out.println(" End of search.\n");
	} // method search

	/*************************************************************************
	 * Method: list                                                          *
	 * Purpose: Lists the contents of the selected binary search tree.       *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'b_availability' = true ->B.S.T. for In Stock Movies        *
	 *                              false->B.S.T. for Checked Out Movies     *
	 * Output: none                                                          *
	 *************************************************************************/
	public static void list(boolean b_availability)
	{
		System.out.println(" List:\n");

		/* LIST BASED ON SELECTED AVAILABILITY */
		if(b_availability)
			Videos_in.print_movies();
		else
			Videos_out.print_movies();

		System.out.println(" End of list.\n");
	} // method list

	/*************************************************************************
	 * Method: add                                                           *
	 * Purpose: Adds a movie to the appropriate binary search tree.          *
	 * Input: none                                                           *
	 * Output: none                                                          *
	 *************************************************************************/
	public static void add()
	{
		/* LOCAL VARIABLES */
		Video Video_add = new Video();	// VIDEO OBJECT FOR MOVIE TO BE ADDED

		/* STANDARD TEXT INPUT STREAM SETUP */
		BufferedReader br_std_in = new BufferedReader( new InputStreamReader(System.in) );

		/* INPUT OF MOVIE PROPERTIES */
		try
		{
			System.out.println(" Input of video properties . . . ");

			System.out.print("Title? ");
			System.out.flush();
			Video_add.str_title = br_std_in.readLine();
			System.out.print("Release Year? ");
			System.out.flush();
			Video_add.int_year = Integer.parseInt( br_std_in.readLine() );
			System.out.print("Runtime in Minutes? ");
			System.out.flush();
			Video_add.int_runtime = Integer.parseInt( br_std_in.readLine() );
			System.out.print("Availability [true,false]? ");
			System.out.flush();
			Video_add.str_available = br_std_in.readLine();
			Video_add.Video_left = null;
			Video_add.Video_right = null;

			System.out.println(" Input complete.\n");
		} // try
		/* EXCEPTION HANDLING */
		catch(IOException exception)
		{
			System.out.println(" FATAL EXCEPTION: File input problem.");
			System.exit(-1);
		} // catch
		catch(NumberFormatException exception)
		{
			System.out.println(" FATAL EXCEPTION: Invalid Release Year/Runtime.  Must be a number.");
			System.exit(-1);
		} // catch

		/* ADD MOVIE */
		System.out.println(" Adding the title '"+Video_add.str_title+"' . . . ");

		// => ADD TO IN STOCK LINKED LIST
		if( Video_add.str_available.equals("true") )
			Videos_in.insert_movie(Video_add);
		// => ADD TO CHECKED OUT STOCK LINKED LIST
		else if( Video_add.str_available.equals("false") )
			Videos_out.insert_movie(Video_add);

		System.out.println(" Done adding.\n");

		return;
	} // method add

	/*************************************************************************
	 * Method: remove                                                        *
	 * Purpose: Removes the given movie from the appropriate binary search   *
	 *          tree.                                                        *
	 * Input: --PARAMATERS--                                                 *
 	 *        => 'str_given' = The title for which to remove.                *
	 * Output: none                                                          *
	 *************************************************************************/
	public static void remove(String str_given)
	{
		/* LOCAL VARIABLES */
		Video Video_in_result;	// VIDEO OBJECT FOR RESULT MOVIE FROM IN STOCK B.S.T.
		Video Video_out_result;	// VIDEO OBJECT FOR RESULT MOVIE FROM CHECKED OUT B.S.T.
		boolean b_in;			// BOOLEAN FOR EXISTENCE OF MOVIE AS IN STOCK VIDEO
		boolean b_out;			// BOOLEAN FOR EXISTENCE OF MOVIE AS CHECKED OUT VIDEO

		/* VERIFY EXISTENCE */
		System.out.println(" Verifying existence of '"+str_given+"' . . . ");

		// => IN STOCK LINKED LIST
		Video_in_result = Videos_in.find_movie(str_given);

		if(Video_in_result != null)
			b_in = true;
		else
			b_in = false;

		// => CHECKED OUT LINKED LIST
		Video_out_result = Videos_out.find_movie(str_given);

		if(Video_out_result != null)
			b_out = true;
		else
			b_out = false;

		// => RESULTS
		if(!b_in && !b_out)
		{
			System.out.println(" ERROR: The title '"+str_given+"' is NOT carried.\n"+
			                   " End of verifying existence.\n");
			return;
		} // if
		else
		{
			System.out.println(" The title '"+str_given+"' is carried.\n"+
			                   " End of verifying existence.\n");
		} // else

		/* REMOVE MOVIE */
		System.out.println(" Removing the title '"+str_given+"' . . . ");

		// => DELETE FROM IN STOCK LINKED LIST
		if(b_in)
			Videos_in.delete_movie(str_given);
		// => DELETE FROM CHECKED OUT STOCK LINKED LIST
		else
			Videos_out.delete_movie(str_given);

		System.out.println(" Done removing.\n");
	} // method remove

	/*************************************************************************
	 * Method: export                                                        *
	 * Purpose: Writes the contents of both binary search trees to the given *
	 *          file as a video database.                                    *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'str_database' = The filename of the video database.        *
	 * Output: --EXIT VALUES--                                               *
	 *         => FATAL EXCEPTION = -1                                       *
	 *************************************************************************/
	public static void export(String str_database)
	{
		try
		{
			/* FILE OUTPUT STREAM SETUP FOR DATABASE */
			BufferedWriter bw_file_out = new BufferedWriter( new FileWriter(str_database) );

			System.out.println(" Exporting database to '"+str_database+"' . . . ");

			bw_file_out = Videos_in.write_movies(bw_file_out);
			bw_file_out = Videos_out.write_movies(bw_file_out);

			bw_file_out.close();

			System.out.println(" Done exporting.\n");
		} // try
		catch(IOException exception)
		{
			System.out.println(" FATAL EXCEPTION: File output problem.");
			System.exit(-1);
		} // catch
	} // method export
} // class Database
