/*********************************************************************
 * Author: B. Alex Bridges                                           *
 * Login ID: brid0129                                                *
 * Class: CPSC-102, Summer 1998                                      *
 * Project: Programming Assignment 5                                 *
 * Description: This program is a simple database query system for a *
 *              video store.                                         *
 * Contents: Methods for program commands.                           *
 *********************************************************************/

/* IMPORTS */
import java.io.*;


class Database
{
	/* CONSTANTS */
	final static boolean b_debug = false;	// CONTROLS EXTRA DEBUG OUTPUT

	/* GLOBAL VARIABLES */
	public static Videos Videos_in;				// B.S.T. OF IN STOCK VIDEOS
	public static Videos Videos_out;			// B.S.T. OF CHECKED OUT VIDEOS
																				// B.S.T. = BINARY SEARCH TREE

	/*************************************************************************
	 * 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 B.S.T.                                           *
	 * 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) );

			Prog5.TArea_output.append(" Reading the video database '"+str_database+"' . . . \n");

			/* 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

			Prog5.TArea_output.append(" Read completed.\n \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_result_in;	// RESULT VIDEO OBJECT FROM IN STOCK B.S.T.
		Video Video_result_out;	// RESULT VIDEO OBJECT FROM CHECKED OUT B.S.T.
		boolean b_in;						// BOOLEAN FOR EXISTENCE AS IN STOCK VIDEO
		boolean b_out;					// BOOLEAN FOR EXISTENCE AS CHECKED OUT VIDEO

		/* VERIFY EXISTENCE */
		Prog5.TArea_output.append(" Verifying existence of '"+str_given+"' . . . \n");

		// => IN STOCK DATABASE
		Video_result_in = Videos_in.find_movie(str_given);

		if(Video_result_in != null)
			b_in = true;
		else
			b_in = false;

		// => CHECKED OUT DATABASE
		Video_result_out = Videos_out.find_movie(str_given);

		if(Video_result_out != null)
			b_out = true;
		else
			b_out = false;

		// => RESULTS
		if(!b_in && !b_out)
		{
			Prog5.TArea_output.append(" ERROR: The title '"+str_given+"' is NOT carried.\n"+
			                          " End of verifying existence.\n \n");
			return;
		} // if
		else
		{
			Prog5.TArea_output.append(" The title '"+str_given+"' is carried.\n"+
			                          " End of verifying existence.\n \n");
		} // else

		/* VERIFY STATUS */
		Prog5.TArea_output.append(" Verifying status of '"+str_given+"' . . . \n");

		// => RETURNING VIDEO, BUT ALREADY IN STOCK
		if(b_availability && b_in)
		{
			Prog5.TArea_output.append(" ERROR: The title '"+str_given+"' is already in stock.\n"+
			                          " End of verifying status.\n \n");
			return;
		} // if
		// => CHECKING OUT VIDEO, BUT ALREADY CHECKED OUT
		else if (!b_availability && b_out)
		{
			Prog5.TArea_output.append(" ERROR: The title '"+str_given+"' is already checked out.\n"+
			                          " End of verifying status.\n \n");
			return;
		} // if
		// => RETURNING VIDEO WHICH IS CHECKED OUT
		else if(b_availability && !b_in && b_out)
		{
			Prog5.TArea_output.append(" The title '"+str_given+"' can be returned.\n"+
			                          " End of verifying status.\n \n");
		} // if
		// => CHECKING OUT VIDEO WHICH IS IN STOCK
		else if(!b_availability && b_in && !b_out)
		{
			Prog5.TArea_output.append(" The title '"+str_given+"' can be checked out.\n"+
			                          " End of verifying status.\n \n");
		} // if
		else
			Prog5.TArea_output.append(" 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 \n");

		/* CHECK OUTS */
		if(!b_availability)
		{
			Prog5.TArea_output.append(" Checking out the title '"+str_given+"' . . . \n");

			// => ADJUST AVAILABILITY
			Video_result_in.str_available = "false";

			// => DELETE FROM IN STOCK DATABASE
			Videos_in.delete_movie(str_given);

			// => INSERT INTO CHECKED OUT DATABASE
			Videos_out.insert_movie(Video_result_in);

			Prog5.TArea_output.append(" Done checking out.\n \n");
		} // if
		/* RETURNS */
		else
		{
			Prog5.TArea_output.append(" Returning the title '"+str_given+"' . . . \n");

			// => ADJUST AVAILABILITY
			Video_result_out.str_available = "true";

			// => DELETE FROM CHECKED OUT DATABASE
			Videos_out.delete_movie(str_given);

			// => INSERT INTO IN STOCK DATABASE
			Videos_in.insert_movie(Video_result_out);

			Prog5.TArea_output.append(" Done returning.\n \n");
		} // else
	} // method availability

	/*************************************************************************
	 * Method: search                                                        *
	 * Purpose: Searches both B.S.T.s 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

		Prog5.TArea_output.append(" Searching for '"+str_given+"' . . . \n");

		/* IN STOCK DATABASE */
		Video_found = Videos_in.find_movie(str_given);
		if(Video_found != null)
		{
			Prog5.TArea_output.append(" The title '"+str_given+"' was found to be in stock.\n \n");
			Videos.print_movie(Video_found);
		} // if
		else
			Prog5.TArea_output.append(" The title '"+str_given+"' was NOT found to be in stock.\n");

		/* CHECKED OUT DATABASE */
		Video_found = Videos_out.find_movie(str_given);
		if(Video_found != null)
		{
			Prog5.TArea_output.append(" The title '"+str_given+"' was found to be checked out.\n \n");
			Videos.print_movie(Video_found);
		} // if
		else
			Prog5.TArea_output.append(" The title '"+str_given+"' was NOT found to be checked out.\n");

		Prog5.TArea_output.append(" End of search.\n \n");
	} // method search

	/*************************************************************************
	 * Method: list                                                          *
	 * Purpose: Lists the contents of the selected B.S.T.                    *
	 * 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)
	{
		Prog5.TArea_output.append(" List:\n \n");

		/* LIST BASED ON SELECTED AVAILABILITY */
		if(b_availability)
			Videos_in.print_movies();
		else
			Videos_out.print_movies();

		Prog5.TArea_output.append(" End of list.\n \n");
	} // method list

	/*************************************************************************
	 * Method: add                                                           *
	 * Purpose: Adds a movie to the appropriate B.S.T.                       *
	 * Input: --PARAMETERS--                                                 *
	 *        => 'Video_add' = The video which is to be added.               *
	 * Output: none                                                          *
	 *************************************************************************/
	public static void add(Video Video_add)
	{
		/* ADD MOVIE */
		Prog5.TArea_output.append(" Adding the title '"+Video_add.str_title+"' . . . \n");

		// => ADD TO IN STOCK DATABASE
		if( Video_add.str_available.equals("true") )
			Videos_in.insert_movie(Video_add);
		// => ADD TO CHECKED OUT STOCK DATABASE
		else if( Video_add.str_available.equals("false") )
			Videos_out.insert_movie(Video_add);
		else
			Prog5.TArea_output.append(" ERROR: Availability of '"+Video_add.str_available+"' invalid.\n"+
			                          "        Must be 'true' or 'false'.");

		Prog5.TArea_output.append(" Done adding.\n \n");

		return;
	} // method add

	/*************************************************************************
	 * Method: remove                                                        *
	 * Purpose: Removes the given movie from the appropriate B.S.T.          *
	 * Input: --PARAMATERS--                                                 *
 	 *        => 'str_given' = The title for which to remove.                *
	 * Output: none                                                          *
	 *************************************************************************/
	public static void remove(String str_given)
	{
		/* LOCAL VARIABLES */
		Video Video_result_in;	// RESULT VIDEO OBJECT FROM IN STOCK B.S.T.
		Video Video_result_out;	// RESULT VIDEO OBJECT FROM CHECKED OUT B.S.T.
		boolean b_in;						// BOOLEAN FOR EXISTENCE AS IN STOCK VIDEO
		boolean b_out;					// BOOLEAN FOR EXISTENCE AS CHECKED OUT VIDEO

		/* VERIFY EXISTENCE */
		Prog5.TArea_output.append(" Verifying existence of '"+str_given+"' . . . \n");

		// => IN STOCK DATABASE
		Video_result_in = Videos_in.find_movie(str_given);

		if(Video_result_in != null)
			b_in = true;
		else
			b_in = false;

		// => CHECKED OUT DATABASE
		Video_result_out = Videos_out.find_movie(str_given);

		if(Video_result_out != null)
			b_out = true;
		else
			b_out = false;

		// => RESULTS
		if(!b_in && !b_out)
		{
			Prog5.TArea_output.append(" ERROR: The title '"+str_given+"' is NOT carried.\n"+
			                          " End of verifying existence.\n \n");
			return;
		} // if
		else
		{
			Prog5.TArea_output.append(" The title '"+str_given+"' is carried.\n"+
			                          " End of verifying existence.\n \n");
		} // else

		/* REMOVE MOVIE */
		Prog5.TArea_output.append(" Removing the title '"+str_given+"' . . . \n");

		// => DELETE FROM IN STOCK DATABASE
		if(b_in)
			Videos_in.delete_movie(str_given);
		// => DELETE FROM CHECKED OUT DATABASE
		else
			Videos_out.delete_movie(str_given);

		Prog5.TArea_output.append(" Done removing.\n \n");
	} // method remove

	/*************************************************************************
	 * Method: export                                                        *
	 * Purpose: Writes the contents of both B.S.T.s 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) );

			Prog5.TArea_output.append(" Exporting database to '"+str_database+"' . . . \n");

			bw_file_out = Videos_in.write_movies(bw_file_out);
			bw_file_out = Videos_out.write_movies(bw_file_out);

			bw_file_out.close();

			Prog5.TArea_output.append(" Done exporting.\n \n");
		} // try
		catch(IOException exception)
		{
			System.out.println(" FATAL EXCEPTION: File output problem.");
			System.exit(-1);
		} // catch
	} // method export
} // class Database
