/*********************************************************************
 * 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 dealing with Video objects.                 *
 *********************************************************************/

/* IMPORTS */
import java.io.*;


class Videos
{
	/* CONSTANTS */
	final static boolean b_debug = false;	// CONTROLS EXTRA DEBUG OUTPUT
	final static String str_default = "";	// DEFAULT STRING VALUE
	final static int int_default = -1;		// DEFAULT INTEGER VALUE

	/* OBJECT VARIABLES */
	private Video Video_root;				// VIDEO OBJECT FOR POINTER TO ROOT NODE
	                                        // OF IN-STOCK B.S.T.
	                                        // (OR NULL FOR EMPTY TREE)


	/*************************************************************************
	 * Method: get_movie                                                     *
	 * Purpose: Gets the movie properties--title, release year, runtime,     *
	 *          and availabilty.                                             *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'br_file_in' = The BufferedReader for the video database.   *
	 * Output: --RETURNS--                                                   *
	 *        => SUCCESS = The movie.                                        *
	 *        => FAILURE = null                                              *
	 *************************************************************************/
	public static Video get_movie(BufferedReader br_file_in)
	{
		/* LOCAL VARIABLES */
		Video Video_read = new Video();	// VIDEO OBJECT FOR READ MOVIE

		/* READING OF MOVIE PROPERTIES */
		try
		{
			Video_read.str_title = br_file_in.readLine();
			Video_read.int_year = Integer.parseInt( br_file_in.readLine() );
			Video_read.int_runtime = Integer.parseInt( br_file_in.readLine() );
			Video_read.str_available = br_file_in.readLine();
			Video_read.Video_left = null;
			Video_read.Video_right = null;

			return Video_read;
		} // try
		/* EXCEPTION HANDLING */
		catch(IOException exception)
		{
			System.out.println(" FATAL EXCEPTION: File input problem.");
			return null;
		} // catch
	} // method get_movie

	/*************************************************************************
	 * Method: print_movies                                                  *
	 * Purpose: Calls the private method print_movies_r.                     *
	 * Input: none                                                           *
	 * Output: none                                                          *
	 *************************************************************************/
	public void print_movies()
	{
		print_movies_r(Video_root);
	} // method print_movies

	/*************************************************************************
	 * Method: print_movies_r                                                *
	 * Purpose: Recursively prints a binary search tree of movies.           *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'Video_tree'= The B.S.T. of movies.                         *
	 * Output: none                                                          *
	 *************************************************************************/
	private static void print_movies_r(Video Video_tree)
	{
		/* NON-EMPTY NODE */
		if(Video_tree != null)
		{
			print_movies_r(Video_tree.Video_left);
			print_movie(Video_tree);
			print_movies_r(Video_tree.Video_right);
		} // if
	} // method print_movies_r

	/*************************************************************************
	 * Method: print_movie                                                   *
	 * Purpose: Prints a movie's properties--title, release year, runtime,   *
	 *          and availabilty.                                             *
	 *        => 'Video_print'= The movie which is to be printed.            *
	 * Output: none                                                          *
	 *************************************************************************/
	public static void print_movie(Video Video_print)
	{
		/* PRINTING OF MOVIE PROPERTIES */
		System.out.print("Title: "+Video_print.str_title+"\n"+
		                 "Released: "+Video_print.int_year+"\n"+
		                 "Runtime: "+Video_print.int_runtime+" minutes\n");
		if( Video_print.str_available.equals("false") )
			System.out.println("Available: No\n");
		else if( Video_print.str_available.equals("true") )
			System.out.println("Available: Yes\n");
		else
			System.out.println(" ERROR: Availability of '"+Video_print.str_available+"' is invalid. Must be 'true' or 'false'.\n");
	} // method print_movie

	/*************************************************************************
	 * Method: write_movies                                                  *
	 * Purpose: Calls the private method write_movies_r.                     *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'bw_file_out' = The original B.W. for the video database.   *
	 * Output: --RETURNS--                                                   *
	 *         => 'bw_file_out' = The updated B.W. for the video database.   *
	 *************************************************************************/
	public BufferedWriter write_movies(BufferedWriter bw_file_out)
	{
		return( write_movies_r(bw_file_out, Video_root) );
	} // method write_movies

	/*************************************************************************
	 * Method: write_movies_r                                                *
	 * Purpose: Recursively writes a binary search tree of movies.           *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'bw_file_out' = The original B.W. for the video database.   *
	 *        => 'Video_tree'  = The B.S.T. of movies.                       *
	 * Output: --RETURNS--                                                   *
	 *        => 'bw_file_out' = The updated B.W. for the video database.    *
	 *************************************************************************/
	private static BufferedWriter write_movies_r(BufferedWriter bw_file_out, Video Video_tree)
	{
		/* NON-EMPTY NODE */
		if(Video_tree != null)
		{
			bw_file_out = write_movies_r(bw_file_out, Video_tree.Video_left);
			bw_file_out = write_movie(bw_file_out, Video_tree);
			bw_file_out = write_movies_r(bw_file_out, Video_tree.Video_right);

			return bw_file_out;
		} // if

		/* EMPTY NODE */
		return bw_file_out;
	} // method write_movies_r

	/*************************************************************************
	 * Method: write_movie                                                   *
	 * Purpose: Writes a movie's properties--title, release year, runtime,   *
	 *          and availabilty.                                             *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'bw_file_out' = The original. B.W. for the video database.  *
	 *        => 'Video_write' = The movie which is to be written.           *
	 * Output: --RETURNS--                                                   *
	 *        => 'bw_file_out' = The updated B.W. for the video database.    *
	 *************************************************************************/
	public static BufferedWriter write_movie(BufferedWriter bw_file_out, Video Video_write)
	{
		try
		{
			/* WRITING OF MOVIE PROPERTIES */
			bw_file_out.write(Video_write.str_title);
			bw_file_out.newLine();
			bw_file_out.write( String.valueOf(Video_write.int_year) );
			bw_file_out.newLine();
			bw_file_out.write( String.valueOf(Video_write.int_runtime) );
			bw_file_out.newLine();
			bw_file_out.write(Video_write.str_available);
			bw_file_out.newLine();

			return bw_file_out;
		} // try
		catch(IOException exception)
		{
			System.out.println(" EXCEPTION: File output problem.");
			return null;
		} // catch
	} // method write_movie

	/*************************************************************************
	 * Method: insert_movie                                                  *
	 * Purpose: Calls the private method insert_movie_r.                     *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'Video_insert' = The movie which is to be inserted.         *
	 * Output: none                                                          *
	 *************************************************************************/
	public void insert_movie(Video Video_insert)
	{
		Video_root = insert_movie_r(Video_root, Video_insert);
	} // method insert_movie

	/*************************************************************************
	 * Method: insert_movie_r                                                *
	 * Purpose: Recursively inserts movie into the binary search tree--keep- *
	 *          ing the ascending order by title.                            *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'Video_tree'   = The B.S.T. of movies.                      *
	 *        => 'Video_insert' = The movie which is to be inserted.         *
	 * Output: --RETURNS--                                                   *
	 *        => 'Video_tree' = The new B.S.T. of movies.                    *
	 *************************************************************************/
	private Video insert_movie_r(Video Video_tree, Video Video_insert)
	{
		/* EMPTY NODE */
		if(Video_tree == null)
			return Video_insert;
		/* INSERT < CURRENT NODE */
		else if( Video_insert.str_title.compareTo(Video_tree.str_title) < 0 )
		{
			Video_tree.Video_left = insert_movie_r(Video_tree.Video_left, Video_insert);
			return Video_tree;
		} // if
		/* INSERT > CURRENT NODE */
		else
		{
			Video_tree.Video_right = insert_movie_r(Video_tree.Video_right, Video_insert);
			return Video_tree;
		} // else
	} // method insert_movie_r

	/*************************************************************************
	 * Method: delete_movie                                                  *
	 * Purpose: Calls the private method delete_movie_r.                     *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'str_del' = The title for which to delete.                  *
	 * Output: none                                                          *
	 *************************************************************************/
	public void delete_movie(String str_delete)
	{
		Video_root = delete_movie_r(Video_root, str_delete);
	} // method insert_movie

	/*************************************************************************
	 * Method: delete_movie_r                                                *
	 * Purpose: Recursively deletes movie from the binary search tree.       *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'Video_tree' = The B.S.T. of movies.                        *
	 *        => 'str_del'    = The title for which to delete.               *
	 * Output: --RETURNS--                                                   *
	 *        => 'Video_tree' = The new B.S.T. of movies.                    *
	 *************************************************************************/
	public static Video delete_movie_r(Video Video_tree, String str_del)
	{
		/* EMPTY NODE */
		if(Video_tree == null)
			return null;

		/* NON-EMPTY NODE */
		// => LESS THAN --> TRAVERSE LEFT
		if( str_del.compareTo(Video_tree.str_title) < 0 )
		{
			Video_tree.Video_left = delete_movie_r(Video_tree.Video_left, str_del);
			return Video_tree;
		} // if
		// => GREATER THAN --> TRAVERSE RIGHT
		else if( str_del.compareTo(Video_tree.str_title) > 0 )
		{
			Video_tree.Video_right = delete_movie_r(Video_tree.Video_right, str_del);
			return Video_tree;
		} // if
		// => EQUAL --> DELETE
		else
		{
			if( (Video_tree.Video_left == null) && (Video_tree.Video_right == null) )
				return null;
			else if( Video_tree.Video_left == null)
				return Video_tree.Video_right;
			else if( Video_tree.Video_right == null)
				return Video_tree.Video_left;
			else
			{
				Video Video_swap = Video_tree.Video_right;
				while(Video_swap.Video_left != null)
					Video_swap = Video_swap.Video_left;
				// => TRANSFER DATUMS
				Video_tree.str_title = Video_swap.str_title;
				Video_tree.int_year = Video_swap.int_year;
				Video_tree.int_runtime = Video_swap.int_runtime;
				Video_tree.str_available = Video_swap.str_available;
				Video_tree.Video_right = delete_movie_r(Video_tree.Video_right, Video_swap.str_title);
				return Video_tree;
			} // else
		} // else

	} // method delete_movie_r

	/*************************************************************************
	 * Method: find_movie                                                    *
	 * Purpose: Calls the private method find_movie_r.                       *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'str_search'  = The title for which to search.              *
	 * Output: --RETURNS--                                                   *
	 *        => SUCCESS = The matching movie along with the remaining B.S.T.*
	 *        => FAILURE = null                                              *
	 *************************************************************************/
	public Video find_movie(String str_search)
	{
		return( find_movie_r(Video_root, str_search) );
	} // method find_movie

	/*************************************************************************
	 * Method: find_movie_r                                                  *
	 * Purpose: Searches for movie in the linked list with matching title.   *
	 * Input: --PARAMATERS--                                                 *
	 *        => 'Video_tree' = The B.S.T. of movies.                        *
 	 *        => 'str_search' = The title for which to search.               *
	 * Output: --RETURNS--                                                   *
	 *        => SUCCESS = The matching movie with the remaining linked list.*
	 *        => FAILURE = null                                              *
	 *************************************************************************/
	private static Video find_movie_r(Video Video_tree, String str_search)
	{
		/* EMPTY NODE */
		if(Video_tree == null)
			return Video_tree;

		/* NON-EMPTY NODE */
		// => EQUAL --> STOP
		if( str_search.compareTo(Video_tree.str_title) == 0)
			return Video_tree;
		// => LESS THAN --> TRAVERSE LEFT
		if( str_search.compareTo(Video_tree.str_title) < 0)
			return find_movie_r(Video_tree.Video_left, str_search);
		// => GREATER THAN --> TRAVERSE RIGHT
		else
			return find_movie_r(Video_tree.Video_right, str_search);
	} // method find_movie_r
} // class Videos
