//  $Id: RenderImage.java,v 1.5 2005/04/21 22:49:38 moreland Exp $
//
//  Copyright 2000-2004 The Regents of the University of California.
//  All Rights Reserved.
//
//  Permission to use, copy, modify and distribute any part of this
//  Molecular Biology Toolkit (MBT)
//  for educational, research and non-profit purposes, without fee, and without
//  a written agreement is hereby granted, provided that the above copyright
//  notice, this paragraph and the following three paragraphs appear in all
//  copies.
//
//  Those desiring to incorporate this MBT into commercial products
//  or use for commercial purposes should contact the Technology Transfer &
//  Intellectual Property Services, University of California, San Diego, 9500
//  Gilman Drive, Mail Code 0910, La Jolla, CA 92093-0910, Ph: (858) 534-5815,
//  FAX: (858) 534-7345, E-MAIL:invent@ucsd.edu.
//
//  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
//  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
//  LOST PROFITS, ARISING OUT OF THE USE OF THIS MBT, EVEN IF THE
//  UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//  THE MBT PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND THE
//  UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
//  UPDATES, ENHANCEMENTS, OR MODIFICATIONS. THE UNIVERSITY OF CALIFORNIA MAKES
//  NO REPRESENTATIONS AND EXTENDS NO WARRANTIES OF ANY KIND, EITHER IMPLIED OR
//  EXPRESS, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
//  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR THAT THE USE OF THE
//  MBT WILL NOT INFRINGE ANY PATENT, TRADEMARK OR OTHER RIGHTS.
//  
//  For further information, please see:  http://mbt.sdsc.edu
//  
//  History:
//  $Log: RenderImage.java,v $
//  Revision 1.5  2005/04/21 22:49:38  moreland
//  On exception or error, exit the JVM.
//
//  Revision 1.4  2004/08/24 17:01:41  moreland
//  Added ImageUtils call to autoCropAndScale method.
//
//  Revision 1.3  2004/04/08 23:55:07  moreland
//  Updated copyright to new UCSD wording.
//
//  Revision 1.2  2004/01/30 02:07:36  moreland
//  Updated copyright and class block comments.
//
//  Revision 1.1  2003/12/08 21:41:35  moreland
//  Added RenderImage tool.
//
//  Revision 1.0  2003/09/11 16:06:13  moreland
//  First version.
//  


// Core
import java.applet.*;
import java.util.*;  // Hashtable and Enumeration
import java.io.File;
import java.net.*;

// GUI
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.*;

// MBT
import edu.sdsc.mbt.*;
import edu.sdsc.mbt.io.*;
import edu.sdsc.mbt.viewables.*;
import edu.sdsc.mbt.viewers.*;
import edu.sdsc.mbt.util.*;
import edu.sdsc.mbt.gui.*;
import edu.sdsc.vis.image.*;


/**
 *  This class is the main RenderImage application class.
 *  It is a command-line tool which loads a structure, optionally displays
 *  a thumbnail using a StructureViewer, then saves the rendered image at a
 *  requested width and height to the specified image file.
 *  <P>
 *  @author	John L. Moreland
 */
public class RenderImage
{
	// GUI
	protected JFrame renderImageFrame = null;
	protected Container renderImageFrameContainer = null;

	// Viewers
	private StructureViewer structureViewer = null;

	// Runtime properties (options or parameters)
	private Properties properties = new Properties( );


	/*********************************************************************/
	/***************************  ENTRY POINTS  **************************/
	/*********************************************************************/


	/*********************************************************************/
	/*                                                                   */
	/*  The main program entry point when invoked as an application.     */
	/*                                                                   */
	/*********************************************************************/
	public static void main( String[] args )
	{
		RenderImage renderImage = new RenderImage();
		if ( args != null )
		{
			for ( int i=0; i<args.length; i++ )
			{
				if ( args[i].equals( "-f" ) )
					renderImage.properties.setProperty( "file", args[++i] );
				if ( args[i].equals( "-u" ) )
					renderImage.properties.setProperty( "url", args[++i] );
				if ( args[i].equals( "-p" ) )
					renderImage.properties.setProperty( "pdbid", args[++i] );

				// Output an image to the specified file name.
				if ( args[i].equals( "-i" ) )
					renderImage.properties.setProperty( "image", args[++i] );
				// Set the width of the output image to the specified size.
				if ( args[i].equals( "-xsize" ) )
					renderImage.properties.setProperty( "xsize", args[++i] );
				// Set the height of the output image to the specified size.
				if ( args[i].equals( "-ysize" ) )
					renderImage.properties.setProperty( "ysize", args[++i] );

				// Turn preview on (off by default).
				if ( args[i].equals( "-preview" ) )
					renderImage.properties.setProperty( "preview", "on" );

			}
		}

		// If something crashes and any type of exception is thrown
		// all the way back to here, make sure that we exit the JVM.
		try
		{
			renderImage.initialize();
		}
		catch ( Exception ex )
		{
			Status.output( Status.LEVEL_ERROR, ex.toString() );
			ex.printStackTrace( );
			System.exit( 1 );
		}
		catch ( Error er )
		{
			Status.output( Status.LEVEL_ERROR, er.toString() );
			er.printStackTrace( );
			System.exit( 1 );
		}
	}


	/*********************************************************************/
	/**************************  INITIALIZATION  *************************/
	/*********************************************************************/


	/**
	 *  Initializes the RenderImage.
	 */
	public void initialize()
	{
		// Build the frame
		renderImageFrame = new JFrame( "RenderImage" );
		renderImageFrameContainer = renderImageFrame.getContentPane();
		renderImageFrameContainer.setLayout( new BorderLayout() );

		// Create a StructureViewer
		structureViewer = new StructureViewer( );
		renderImageFrameContainer.add( BorderLayout.CENTER, structureViewer );

		// Determine the image size.
		int imageWidth = 320;
		int imageHeight = 240;
		String xsize = properties.getProperty( "xsize" );
		if ( xsize != null ) imageWidth = Integer.parseInt( xsize );
		String ysize = properties.getProperty( "ysize" );
		if ( ysize != null ) imageHeight = Integer.parseInt( ysize );

		// Pack the frame
		renderImageFrame.pack( );
		renderImageFrame.validate( );
		// renderImageFrame.setSize( imageWidth, imageHeight );
		float imageAspect = (float) imageWidth / (float) imageHeight;
		int previewWidth = 200;
		int previewHeight = (int) ((float)previewWidth / imageAspect);
		renderImageFrame.setSize( previewWidth, previewHeight );
		if ( properties.getProperty( "preview" ) != null )
			renderImageFrame.setVisible( true );

		//
		// See if the runtime properties specify a Structure to load.
		//

		Structure structure = null;
		String dataset = null;
		if ( properties.getProperty( "file" ) != null )
		{
			dataset = properties.getProperty( "file" );
			structure = StructureFactory.load( new File( dataset ) );
		}
		else if ( properties.getProperty( "url" ) != null )
		{
			dataset = properties.getProperty( "url" );
			try
			{
				structure = StructureFactory.load( new URL( dataset ) );
			}
			catch ( MalformedURLException e )
			{
				Status.output( Status.LEVEL_ERROR, e.toString() );
			}
		}
		else if ( properties.getProperty( "pdbid" ) != null )
		{
			dataset = properties.getProperty( "pdbid" );
			try
			{
				String urlString = "ftp://beta.rcsb.org/pub/pdb/uniformity/data/mmCIF.gz/all/" + dataset.toLowerCase() + ".cif.gz";
				structure = StructureFactory.load( new URL( urlString ) );
			}
			catch ( MalformedURLException e )
			{
				Status.output( Status.LEVEL_ERROR, e.toString() );
			}
		}

		if ( dataset == null )
		{
			Status.output( Status.LEVEL_REMARK, "No data set specified!" );
			System.exit( 1 );
		}

		if ( structure == null )
		{
			Status.output( Status.LEVEL_REMARK, "Could not load: " + dataset );
			System.exit( 2 );
		}

		Status.output( Status.LEVEL_REMARK, "Data set loaded: " + dataset );

		// Show the Structure's UrlString in the title bar.
		renderImageFrame.setTitle( "MBT RenderImage: " + structure.getUrlString() );

		// View the Structure
		StructureDocument structureDocument = new StructureDocument( );
		structureDocument.addStructure( structure );
		structureDocument.addViewer( structureViewer );

		// Save the rendered image to a file.
		String imagePath = properties.getProperty( "image" );
		if ( imagePath == null )
		{
			Status.output( Status.LEVEL_ERROR, "No image file specified" );
			System.exit( 1 );
		}
		File file = new File( imagePath );
        BufferedImage image = structureViewer.getBufferedImage( imageWidth, imageHeight );
		image = ImageUtils.autoCropAndScale( image, imageWidth, imageHeight );
		ImageFileManager imageFileManager =
			new ImageFileManager( renderImageFrame );
		imageFileManager.save( image, file );

		// Exit (get a clean exit from GUI threads).
		System.exit( 0 );
	}
}

