// Aqsis
// Copyright (c) 1997 - 2001, Paul C. Gregory
//
// Contact: pgregory@aqsis.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/**
 * Copyright (C) 2006-2007  NTT DATA CORPORATION
 * 
 * Version: 1.0.0 2007/04/01
 *  
 */
package net.cellcomputing.himawari.main;

import static net.cellcomputing.himawari.library.RendermanInterface.RiBegin;
import static net.cellcomputing.himawari.library.RendermanInterface.RiCropWindow;
import static net.cellcomputing.himawari.library.RendermanInterface.RiDisplay;
import static net.cellcomputing.himawari.library.RendermanInterface.RiEnd;
import static net.cellcomputing.himawari.library.RendermanInterface.RiOption;
import static net.cellcomputing.himawari.library.RendermanInterface.RiPreWorldFunction;
import static net.cellcomputing.himawari.library.RendermanInterface.RiProgressHandler;
import static net.cellcomputing.himawari.main.Globalmain.VERSION_STR;
import static net.cellcomputing.himawari.main.Globalmain.g_archive_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_Progress;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_addtype;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_archive_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_beep;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_cropWindow;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_display_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_dso_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_endofframe;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_fb;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_frames;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_framesList;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_help;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_mode;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_no_color;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_nostandard;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_pause;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_plugin_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_procedural_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_progress;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_rc_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_rinfo;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_shader_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_strprogress;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_texture_path;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_type;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_verbose;
import static net.cellcomputing.himawari.main.Globalmain.g_cl_version;
import static net.cellcomputing.himawari.main.Globalmain.g_display_path;
import static net.cellcomputing.himawari.main.Globalmain.g_dso_path;
import static net.cellcomputing.himawari.main.Globalmain.g_plugin_path;
import static net.cellcomputing.himawari.main.Globalmain.g_procedural_path;
import static net.cellcomputing.himawari.main.Globalmain.g_rc_path;
import static net.cellcomputing.himawari.main.Globalmain.g_shader_path;
import static net.cellcomputing.himawari.main.Globalmain.g_texture_path;
import static net.cellcomputing.himawari.parser.Global.StandardDeclarations;
import static net.cellcomputing.himawari.main.Globalmain.g_enc_flag;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;

import net.cellcomputing.himawari.accessory.primitive.p_String;
import net.cellcomputing.himawari.accessory.primitive.p_int;
import net.cellcomputing.himawari.argparse.ArgParse;
import net.cellcomputing.himawari.display.DisplayManager;
import net.cellcomputing.himawari.library.RiGlobal;
import net.cellcomputing.himawari.parser.Global;
import net.cellcomputing.himawari.parser.Parser;
import net.cellcomputing.himawari.util.HimawariLogger;

/**
 * 
 * メインクラス
 * 
 * @author NTT DATA Corporation
 */
public strictfp class Himawari {
	
	public static void main(String[] args) {
		
		//パスの設定 ： WINDOWS仕様で統一　： AQSIS_SYSTEM_WIN32
		String acPath = System.getProperty( "user.dir" ); 
		String rootPath = acPath.concat( File.separator );
		
		g_rc_path = rootPath;
		g_shader_path = rootPath.concat( "shaders" );
		g_archive_path = rootPath.concat( "archives" ) ;
		g_texture_path = rootPath.concat( "textures" );
		g_display_path = rootPath.concat( "bin" );
		g_dso_path = rootPath.concat( "dsos" );
		g_procedural_path = rootPath.concat( "procedures" );
		g_plugin_path = rootPath.concat( "plugins" );
		
		//Debug用　:　StartMemoryDebugging();
		{
			//用意するオプションを登録
			ArgParse ap = new ArgParse();
			ap.usageHeader( new String( "Usage: " ) + Himawari.class.getSimpleName()+ " [options] [RIB file...]" );
			ap.argFlag( "help", "\tPrint this help and exit", g_cl_help );
			ap.alias( "help" , "h" );
			ap.argFlag( "version", "\tPrint version information and exit", g_cl_version );
			ap.argFlag( "pause", "\tWait for a keypress on completion", g_cl_pause );
			ap.argFlag( "progress", "\tPrint progress information", g_cl_progress );
			ap.argFlag( "Progress", "\tPrint prman-compatible progress information (ignores -progressformat)", g_cl_Progress );
			ap.argString( "progressformat", "=string printf-style format string for -progress", g_cl_strprogress );
			ap.argInt( "endofframe", "=integer\tEquivalent to \"endofframe\" RIB option", g_cl_endofframe );
			ap.argFlag( "nostandard", "\tDo not declare standard RenderMan parameters", g_cl_nostandard );
			ap.argInt( "verbose", "=integer\tSet log output level\n" +
					"\t0 = errors\n" +
					"\t1 = warnings (default)\n" +
					"\t2 = information\n" +
					"\t3 = debug", g_cl_verbose );
			ap.alias( "verbose", "v" );
			ap.argFlag( "renderinfo", "\tPrint out infos about base rendering settings", g_cl_rinfo );
			ap.argString( "type", "=string\tSpecify a display device type to use", g_cl_type );
			ap.argString( "addtype", "=string\tSpecify a display device type to add", g_cl_addtype );
			ap.argString( "mode", "=string\tSpecify a display device mode to use", g_cl_mode );
			ap.argFlag( "fb", "\tSame as --type=\"framebuffer\" --mode=\"rgb\"", g_cl_fb );
			ap.alias( "fb", "d" );
			ap.argFloats( "crop", " x1 x2 y1 y2\tSpecify a crop window, values are in screen space.", g_cl_cropWindow, ArgParse.SEP_ARGV, 4);
			ap.argString( "rc", "=string\tOverride the default RIB configuration file [" + g_rc_path + "]", g_cl_rc_path );
			ap.argString( "shaders", "=string\tOverride the default shader searchpath(s) [" + g_shader_path + "]", g_cl_shader_path );
			ap.argString( "archives", "=string\tOverride the default archive searchpath(s) [" + g_archive_path + "]", g_cl_archive_path );
			ap.argString( "textures", "=string\tOverride the default texture searchpath(s) [" + g_texture_path + "]", g_cl_texture_path );
			ap.argString( "displays", "=string\tOverride the default display searchpath(s) [" + g_display_path + "]", g_cl_display_path );
			ap.argString( "dsolibs", "=string\tOverride the default dso searchpath(s) [" + g_dso_path + "]", g_cl_dso_path );
			ap.argString( "procedurals", "=string\tOverride the default procedural searchpath(s) [" + g_procedural_path + "]", g_cl_procedural_path );
			ap.argString( "plugins", "=string\tOverride the default plugin searchpath(s) [" + g_plugin_path + "]", g_cl_plugin_path );
			ap.argInts( "frames", " f1 f2\tSpecify a starting/ending frame to render (inclusive).", g_cl_frames, ArgParse.SEP_ARGV, 2);
			ap.argString( "frameslist", "=string\tSpecify a range of frames to render, ',' separated with '-' to indicate ranges.", g_cl_framesList);
			ap.argFlag( "nocolor", "\tDisable colored output", g_cl_no_color );
			ap.argFlag( "beep", "\tBeep on completion of all ribs", g_cl_beep );
			ap.alias( "nocolor", "nc" );

			//--2007/02/01 暗号対応のため変更 nttdata
			ap.argFlag("enc","\tRead encrypted file.",g_enc_flag);
			//--
			ap.allowUnrecognizedOptions();

			//_crtBreakAlloc = 1305;
			
			//オプション入力が不正だったときのエラーメッセージを出力
			if ( args.length > 0 && !ap.parse( args.length, args ) ){
				System.err.println( ap.errmsg());	System.err.flush();
				System.err.println( ap.usagemsg());	System.err.flush();
				System.exit( 1 );
			}
			
			// Check that the number of arguments to crop are valid if specified.
			//　cropする場合、引数の数が有効であるかチェックする
			if ( g_cl_cropWindow.size() > 0 && g_cl_cropWindow.size() != 4 ){
				System.out.println( "Error: invalid number of arguments to -crop, expected 4, got " + g_cl_cropWindow.size());
				System.out.flush();
				g_cl_help.value = true;
			}
			
			//ヘルプメッセージ表示
			if ( g_cl_help.value ){
				System.out.println( ap.usagemsg());
				System.exit( 0 );
			}
			
			//バージョン情報と日付を表示
			if ( g_cl_version.value ){
				System.out.print( "himawari version " + VERSION_STR); 
				//	#ifdef _DEBUG
				//	System.out.print( " (debug build)"); 
				//	#endif
//				Date date = new Date();
//				DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
//				System.out.print( "\n" + "compiled " + df.format(date) + "\n");
				System.exit( 0 );
			}
			
			// Apply environment-variable overrides to default paths ...
			//環境変数を取得
			if(System.getenv("HIMAWARI_RC_PATH") != null)
				g_rc_path = System.getenv("HIMAWARI_RC_PATH");
			if(System.getenv("HIMAWARI_SHADER_PATH") != null)
				g_shader_path = System.getenv("HIMAWARI_SHADER_PATH");
			if(System.getenv("HIMAWARI_ARCHIVE_PATH") != null)
				g_archive_path = System.getenv("HIMAWARI_ARCHIVE_PATH");
			if(System.getenv("HIMAWARI_TEXTURE_PATH") != null)
				g_texture_path = System.getenv("HIMAWARI_TEXTURE_PATH");
			if(System.getenv("HIMAWARI_DISPLAY_PATH") != null)
				g_display_path = System.getenv("HIMAWARI_DISPLAY_PATH");
			if(System.getenv("HIMAWARI_DSO_PATH") != null)
				g_dso_path = System.getenv("HIMAWARI_DSO_PATH");
			if(System.getenv("HIMAWARI_PROCEDURAL_PATH") != null)
				g_procedural_path = System.getenv("HIMAWARI_PROCEDURAL_PATH");
			if(System.getenv("HIMAWARI_PLUGIN_PATH") != null)
				g_procedural_path = System.getenv("HIMAWARI_PLUGIN_PATH");
			
			// Apply command-line overrides to default paths ...
			// オプションに対応するパラメータがある場合上書き
			if(g_cl_rc_path.value.length() != 0)
				g_rc_path = g_cl_rc_path.value;
			if(g_cl_shader_path.value.length() != 0)
				g_shader_path = g_cl_shader_path.value;
			if(g_cl_archive_path.value.length() != 0)
				g_archive_path = g_cl_archive_path.value;
			if(g_cl_texture_path.value.length() != 0)
				g_texture_path = g_cl_texture_path.value;
			if(g_cl_display_path.value.length() != 0)
				g_display_path = g_cl_display_path.value;
			if(g_cl_dso_path.value.length() != 0)
				g_dso_path = g_cl_dso_path.value;
			if(g_cl_procedural_path.value.length() != 0)
				g_procedural_path = g_cl_procedural_path.value;
			if(g_cl_plugin_path.value.length() != 0)
				g_plugin_path = g_cl_plugin_path.value;
			
			//ログレベルの設定	
			HimawariLogger logger = HimawariLogger.getLogger();
			logger.setLogLevel( HimawariLogger.LEVEL_ERROR );
			if( g_cl_verbose.value > 0 )
				logger.setLogLevel( HimawariLogger.LEVEL_WARNING );
			if( g_cl_verbose.value > 1 )
				logger.setLogLevel( HimawariLogger.LEVEL_INFO );
			if( g_cl_verbose.value > 2 )
				logger.setLogLevel( HimawariLogger.LEVEL_DEBUG );
			
			//ログエラーの出力
			logger.info( "rc path: " + g_rc_path + "\n"); 
			logger.info( "shader path(s): " + g_shader_path + "\n"); 
			logger.info( "archive path(s): " + g_archive_path + "\n"); 
			logger.info( "texture path(s): " + g_texture_path + "\n"); 
			logger.info( "display path(s): " + g_display_path + "\n"); 
			logger.info( "dso path(s): " + g_dso_path + "\n");
			logger.info( "procedural path(s): " + g_procedural_path + "\n");
			logger.info( "plugin path(s): " + g_plugin_path + "\n"); 
			
			//レンダリングするファイルが指定されない場合、標準入力により取得
			if ( ap.leftovers().size() == 0 ){     // If no files specified, take input from stdin.
				String name = "System.in";
				Himawari.RenderFile( System.in, name );
			}
			else
			{
				//ファイル名を取得し、オープンしてレンダリングへ
				for(int e = 0; e < ap.leftovers().size(); e++)
				{
					try{
						String name = new String(ap.leftovers().get(e));
						DataInputStream file = new DataInputStream( new FileInputStream(name));
						
//						long start ,end;
//						start = System.currentTimeMillis();
						Himawari.RenderFile( file, name );
//						end = System.currentTimeMillis();
						//System.out.printf("total :" + (end -start) + "ms\n");
						file.close();
						
					}catch( IOException ioe){
						//ファイルオープンエラー
						System.err.println("Warning: Cannot open file \"" + ap.leftovers().get(e) + "\"\n"); 
					}
				}
			}
		}
		//DEBUG用　:　StopMemoryDebugging();	
		//	if.g_cl_beep.value)
		//	{
		//		//ビープ音は鳴らさないことになりました。
		//	}
		
		if(g_cl_pause.value)
		{
			System.out.print("Press any key..."); System.out.flush();
			//std::cin.ignore(std::cin.rdbuf()->in_avail() + 1);
			// ストリームバッファに残っている文字列を読み捨てる
				try {
					System.in.read();
					System.in.close();
				} catch (IOException e) {
					return;
				}
		}
		
		return;
	}
	
	static long tick = 0;
	
	/**
	 * レンダリングの進歩を表示する機能。 
	 * コールバックとして、RiProgressHandler呼び出しに使用されている。
	 * 
	 * @param percent   
	 * @param FrameNo
	 */
	public static void PrintProgress(float percent, int FrameNo)
	{
		if ( ( g_cl_progress.value == false ) && ( g_cl_Progress.value == false ) )
	        return ;

	    // If g_Progress is set, 100% have to be reported. In all other cases the 100% are not displayed
	    if ( percent >= 100 && !g_cl_Progress.value )
	    {
	        System.out.print("                                                                              \r");  
	        System.out.flush();
	        return ;
	    }

	    long now;
	    //現在の時刻を1970年1月1日午前0時0分0秒からの通算秒数で取得
	    if ( tick == 0 )
	    	tick = System.currentTimeMillis()/1000;
	
	    now = System.currentTimeMillis()/1000;

	    // Calculate the various values for putting in the string.
//	    float total_secs = 1000.0f * ( ( float ) ( now - tick ) / ( float ) CLOCKS_PER_SEC );
	    float total_secs = ( now - tick );
	    float total_mins = total_secs / 60.0f;
	    float total_hrs = total_mins / 60.0f;
	    float sub_secs = total_secs - ( ( int ) total_mins * 60.0f );
	    float sub_mins = total_mins - ( ( int ) total_hrs * 60.0f );

	    float total_secsleft = ( ( ( float ) 100 / percent ) * total_secs ) - total_secs;
	    float total_minsleft = total_secsleft / 60.0f;
	    float total_hrsleft = total_minsleft / 60.0f;
	    float sub_secsleft = total_secsleft - ( ( int ) total_minsleft * 60.0f );
	    float sub_minsleft = total_minsleft - ( ( int ) total_hrsleft * 60.0f );

	    // Now print the line with substitution.
	    int ipos = 0;
	   
	    String strProgress;

	    int last_percent = 0;  // So we can skip instead of printing the same twice
	    if ( g_cl_Progress.value )  // Override the outputformat
	    {
	        strProgress = "R90000%p%%";
	        percent = (int)percent;
	        if ( last_percent == percent )
	            return;
	        else
	            last_percent = (int) percent; 
	    }
	    else			// Use the default style
	    {
	        strProgress = g_cl_strprogress.value;
	    }
	    
//	    std::ostringstream strOutput;
//	    strOutput.setf( std::ios::fixed );
	    
	    StringBuilder strOutput = new StringBuilder(100);
		
		DecimalFormat dcformat = new DecimalFormat( "00.00" );
	    while ( true )
	    {
	        int itag;
	        itag = strProgress.indexOf( '%', ipos );

	        if( itag == -1 )
	        {
	        	strOutput.append(strProgress.substring(ipos));
	        	break;
	        }
	        else
	        {
	            if ( ipos != itag )
	            	strOutput.append( strProgress.substring(ipos, ipos+(itag-ipos) ));
	            	//	strOutput << strProgress.substr( ipos, itag - ipos ).c_str();
	            	
	            switch ( strProgress.charAt( itag + 1 ))
	            {
	            case 'p':
	            	String percentOut = dcformat.format( percent );
	            	strOutput.append( ' ' );
	            	strOutput.append( percentOut ); 
	            	//strOutput << std::setw( 6 ) << std::setfill( ' ' ) << std::setprecision( 2 ) << percent;
	            	break;
	            	
	            case 's':
	            	strOutput.append( (int)total_secs );
	            	//strOutput << std::setprecision( 0 ) << ( int ) total_secs;
	            	break;
	            	
	            case 'S':
	            	strOutput.append( (int)total_secsleft );
	            	//strOutput << std::setprecision( 0 ) << ( TqInt ) total_secsleft;
	            	break;
	            	
	            case 'm':
	            	strOutput.append( (int)total_mins );
	            	//strOutput << std::setprecision( 0 ) << ( TqInt ) total_mins;
	            	break;
	            	
	            case 'M':
	            	strOutput.append( (int)total_minsleft );
	            	//strOutput << std::setprecision( 0 ) << ( TqInt ) total_minsleft;
	            	break;
	            	
	            case 'h':
	            	strOutput.append( (int)total_hrs );
	            	//strOutput << std::setprecision( 0 ) << ( TqInt ) total_hrs;
	            	break;
	            	
	            case 'H':
	            	strOutput.append( (int)total_hrsleft );
	            	//strOutput << std::setprecision( 0 ) << ( TqInt ) total_hrsleft;
	            	break;
	            	
	            case 't':
	            	strOutput.append( (int)total_hrs + ":" + String.valueOf((int)sub_mins) + ":" + String.valueOf((int)sub_secs));
	            	//strOutput << std::setprecision( 0 ) << ( TqInt ) total_hrs << ":" << ( TqInt ) sub_mins << ":" << ( TqInt ) sub_secs;
	            	break;
	            	
	            case 'T':
	            	strOutput.append( (int)total_hrsleft + ":" + String.valueOf((int)sub_minsleft) + ":" + String.valueOf((int)sub_secsleft));
	            	//strOutput << std::setprecision( 0 ) << ( TqInt ) total_hrsleft << ":" << ( TqInt ) sub_minsleft << ":" << ( TqInt ) sub_secsleft;
	            	break;
	            	
	            case 'f':
	            	strOutput.append( (int)FrameNo );
	            	//strOutput << std::setprecision( 0 ) << ( TqInt ) FrameNo;
	            	break;
	            	
	            case '%':
	            	strOutput.append('%');
	            	//strOutput << '%';
	            	break;
	            }
	            ipos = itag + 2;
	        }
	        
	        if ( ipos >= strProgress.length() )
	        	break;
	    }
	    // Pad to the end of the line.
	    while ( strOutput.length() < 79 )
	    	strOutput.append(' ');
	    	
	    System.out.print( strOutput );
	    
	    if ( g_cl_Progress.value )
	    	System.out.print( "\n" );
	    else
	    	System.out.print( "\r" );
	    
	    System.out.flush();
	    
	}
	
	/**
	 * ワールドがロードされた後、レンダリングが始まる前に特定のオプションをセットアップするために必要な機能。
	 * RiPreWorldFunctionでコールバックされて、使用されています。
	 * 
	 */
	//Function to setup specific options needed after world loading but before rendering.
	//Used as the callback function to a RiPreWorldFunction call.<br>
	public static void PreWorld()
	{
		if ( g_cl_fb.value )
		{
			RiDisplay( "himawari", "framebuffer", "rgb", (Object)null );
		}
		else if ( g_cl_type.value != null && g_cl_type.value.length() != 0 )
		{
			RiDisplay( "himawari"+TypeToExtension(g_cl_type.value), g_cl_type.value, g_cl_mode.value, (Object)null );
		}
		else if ( g_cl_addtype.value != null && g_cl_addtype.value.length() != 0 )
		{
			RiDisplay( "+himawari"+TypeToExtension(g_cl_addtype.value), g_cl_addtype.value, g_cl_mode.value, (Object)null );
		}
		
		// Pass the statistics option onto Aqsis.
		if ( g_cl_endofframe.value >= 0 )
		{
			p_int[] tmp = new p_int[1];
			tmp[0] = g_cl_endofframe;
			RiOption( "statistics", "endofframe", tmp, (Object)null );
		}
		
		// Pass the crop window onto Aqsis.
		if( g_cl_cropWindow.size() == 4 )
		{
			RiCropWindow(g_cl_cropWindow.get(0).floatValue(), g_cl_cropWindow.get(1).floatValue(), g_cl_cropWindow.get(2).floatValue(), g_cl_cropWindow.get(3).floatValue());
		}
	}
	
	private static String TypeToExtension ( String type )
	{
		if( type.equals("tiff") || type.equals("tif") ){
			return ".tif";
		}
		else if( type.equals("bmp") ){
			return ".bmp";
		}
		else if( type.equals("png") ){
			return ".png";
		}
		else if( type.equals("jpg") ){
			return ".jpg";
		}
		else if( type.equals("jpeg2000") ){
			return ".j2k";
		}
		else if( type.equals("hdr") ){
			return ".hdr";
		}
		else{
			return "";
		}
	}
	
	/**
	 * レンダリングをする本体、まずconfigファイルを読み込みその後Ribファイルを読み込む仕組みである。
     * 実際にレンダリングが始まるのはparserでWorldEnd()が読み込まれた後。
	 *
	 * @param file
	 * @param name
	 */
	public static void RenderFile( InputStream file, String name)
	{
		Parser parser = new Parser();
		
		RiBegin( "CRIBBER" );
		
		if ( !g_cl_nostandard.value ){
			StandardDeclarations(  );
		}
		if ( g_cl_rinfo.value )
		{
			//RiOption( "statistics", "renderinfo", g_cl_rinfo, null );
			p_int[] g_cl_rinfo_al = new p_int[1];
			g_cl_rinfo_al[0] = new p_int(1);
			RiOption( "statistics", "renderinfo", g_cl_rinfo_al, null );
		}
		
		p_String[] popt = new p_String[1];
		popt[0] = new p_String();
		popt[0].value = g_shader_path;
		RiOption( "searchpath", "shader", popt, null );
		popt[0].value  = g_archive_path;
		RiOption( "searchpath", "archive", popt, null );
		popt[0].value  = g_texture_path;
		RiOption( "searchpath", "texture", popt, null );
		popt[0].value  = g_display_path;
		RiOption( "searchpath", "display", popt, null );
		popt[0].value  = g_dso_path;
		RiOption( "searchpath", "dsolibs", popt, null );
		popt[0].value  = g_procedural_path;
		RiOption( "searchpath", "procedural", popt, null );
		popt[0].value  = g_plugin_path;
		RiOption( "searchpath", "plugin", popt, null );
		
		try {
			RiProgressHandler( Himawari.class.getMethod("PrintProgress",float.class,int.class) );
			RiPreWorldFunction( Himawari.class.getMethod("PreWorld") );
		} catch (SecurityException e1) {
			HimawariLogger.outputException( e1 );
		} catch (NoSuchMethodException e1) {
			HimawariLogger.outputException( e1 );
		}
		
		
		HimawariLogger logger = HimawariLogger.getLogger();
		logger.info( "Loading config file " + g_rc_path + "\n");
		
		try{

			String rcfile = g_rc_path;	
			if( rcfile != null )
				parser.parse(rcfile);
			
		}catch( FileNotFoundException ioe){
//			logger.info( "Cannot open config file\n" );
		} catch (Exception e) {
			HimawariLogger.outputException( e );
		}
		
		Global.ClearFrames();
		// Pass in specified frame lists.
		if(g_cl_frames.size() == 2)
		{
			Global.AppendFrames(g_cl_frames.get(0) + "-" + g_cl_frames.get(1));
		}
		if(g_cl_framesList.value.length() != 0)
		{
			Global.AppendFrames(g_cl_framesList.value);
		}
		
		
		try {
			parser.parse(name);
		} catch (Exception e) {
			//logger.error(e.getMessage() + "\n");
			HimawariLogger.outputException( e );
		}
		
		RiEnd();
		
		if ( !g_cl_nostandard.value )
		{
			Global.CleanupDeclarations(  );
		}
		parser = null;
	}
	
	
	
	public static synchronized ArrayList<String> start(String[] args) {
		main(args);
		return DisplayManager.getDisplayNames();
	}

}
