package jp.riken.brain.ni.samuraigraph.application;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityText;


/**
 * The main class of this application.
 */
public class SGDrawingServer
	implements SGIApplicationConstants, SGIApplicationTextConstants
{


	/**
	 * 
	 */
	public static String LOOK_AND_FEEL = null;


	/**
	 * 
	 */
	public static int PORT_NUMBER = 5555;


	/**
	 * 
	 */
	public static String PROPERTY_FILE_NAME = null;


	/**
	 * 
	 */
	public static String DATASET_FILE_NAME = null;


	/**
	 * 
	 */
	public static boolean INPUT_FLAG = false;


	/**
	 * main thread
	 */
	private static SGMainFunctions mAppMain = null;
	

	private static SGApplicationProperties mAppProp = null;
	
	private static Connect mConnect = null;
	
	/**
	 * main method
	 * @param args
	 */
	public static void main( String args[] )
	{

		// interpret command lines
		interpretCommands( args );
		
		// load dynamic constant values from property file
		mAppProp = new SGApplicationProperties();
		if ( mAppProp.getStatus() == false )
			System.exit(1); // fatal error
		
		// set look and feel
		if( setLookAndFeel() == false)
			System.exit(1); // fatal error
		
		// create a Main thread
		SGMainFunctions m = null;
		if( PROPERTY_FILE_NAME!=null )
		{
			m = new SGMainFunctions( PROPERTY_FILE_NAME, FILETYPE_PROPERTY, mAppProp );
		}
		else if( DATASET_FILE_NAME!=null )
		{
			m = new SGMainFunctions( DATASET_FILE_NAME, FILETYPE_DATASET, mAppProp );
		}
		else
		{
			m = new SGMainFunctions( mAppProp );
		}

		// create a new thread
//		if( PORT_NUMBER!=-1 )
		{
			try
			{
				// wait till the end of Main thread
				m.waitInit();
				mAppMain = m;
				
				// register event handler for macos x
				MacOSXRegistration();

				// create a server socket object
//				ServerSocket serverSocket
//					= new ServerSocket( SGDrawingServer.PORT_NUMBER );

				// create Connect thread
				if( INPUT_FLAG )
				{
					ServerSocket serverSocket = null;
					mConnect = new Connect( m, serverSocket );
				}
			}
			catch ( Exception ex )
			{
				JOptionPane.showOptionDialog(
					null,
					"Failed to start up Samurai Graph.",
					TITLE_ERROR,
					JOptionPane.DEFAULT_OPTION,
					JOptionPane.WARNING_MESSAGE, 
					null,
					null,
					null
				);
			}
			
		}

//System.out.println("END");
	}



	/**
	 * 
	 */
	private static void interpretCommands( final String[] commands ) {
		
		for( int ii=0; ii<commands.length; ii++ ) {
			if( commands[ii].equals("-p") ) {
				if( ii+1<commands.length ) {
					Integer n = SGUtilityText.getInteger( commands[ii+1] );
					if( n==null ) {
						continue;
					}
					PORT_NUMBER = n.intValue();
				}
			} else if( commands[ii].equals("-prop") ) {
				if( ii+1<commands.length ) {
					PROPERTY_FILE_NAME = commands[ii+1];
				}
			} else if( commands[ii].equals("-dataset") ) {
				if( ii+1<commands.length ) {
					DATASET_FILE_NAME = commands[ii+1];
				}
			} else if( commands[ii].equals("-i") ) {
				INPUT_FLAG = true;
			} else if( commands[ii].equals( "-laf" ) ) {
				if( ii+1<commands.length ) {
					String className = getLookAndFeelClassName( commands[ii+1].toLowerCase() );
					if( className!=null ) {
						LOOK_AND_FEEL = className;
					}
				}
			}
		}

	}


	/**
	 * Returns the class name of look and feel.
	 * @param name - the short name of look and feel
	 * @return the class name of look and feel
	 */
	private static String getLookAndFeelClassName( String name )
	{
		if( name==null )
		{
			throw new IllegalArgumentException("name==null");
		}
		UIManager.LookAndFeelInfo[] lafArray
			= UIManager.getInstalledLookAndFeels();
		for( int ii=0; ii<lafArray.length; ii++ )
		{
			String name_ = lafArray[ii].getName().toLowerCase();
			if( name_.equals(name.toLowerCase()) )
			{
				LOOK_AND_FEEL = lafArray[ii].getClassName();
			}
		}
		return null;
	}

	// set look and feel
	private static boolean setLookAndFeel()
	{
		try
		{
			if( LOOK_AND_FEEL==null )
			{
				// avoid NPE at non en_US locale for JRE 1.6
				UIManager.getInstalledLookAndFeels();
				UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
			}
			else
			{
				UIManager.setLookAndFeel( LOOK_AND_FEEL );
			}
		}
		catch( Exception ex )
		{
			return false;
		}
		return true;
	}


	private static void MacOSXRegistration()
	{
		boolean isMacOSX = (System.getProperty("os.name").toLowerCase().startsWith("mac os x"));
		if( isMacOSX ){
			try {
				Class osxAdapter = Class.forName("jp.riken.brain.ni.samuraigraph.platform.macosx.SGMacOSXAdapter");
				Method registerMethod = osxAdapter.getMethod("registerMacOSXApplication", null);
				if( registerMethod != null )
				{
				    registerMethod.invoke( osxAdapter, null );
				}
			}
			catch (NoClassDefFoundError e)
			{
				// This will be thrown first if the OSXAdapter is loaded on a system without the EAWT
				// because OSXAdapter extends ApplicationAdapter in its def
				System.err.println("This version of Mac OS X does not support the Apple EAWT.  Application Menu handling has been disabled (" + e + ")");
			}
			catch (ClassNotFoundException e) {
				// This shouldn't be reached; if there's a problem with the OSXAdapter we should get the 
				// above NoClassDefFoundError first.
				System.err.println("This version of Mac OS X does not support the Apple EAWT.  Application Menu handling has been disabled (" + e + ")");
			}
			catch (Exception e)
			{
			    e.printStackTrace();
			}
		}
	}
	
	/**
	 * quit handler for application adapter
	 *
	 */
	public static boolean quitHandler()
	{
	    if ( mAppMain == null ) {
	        return false;
	    }
	    mAppMain.exit();
	    return true;
	}
	
	/**
	 * about handler for application adapter
	 *
	 */
	public static boolean aboutHandler()
	{
	    if ( mAppMain == null ){
	        return false;
	    }
	    return mAppMain.showAboutDialog( null );
	}
	
	/**
	 * openFile handler for application adapter
	 *
	 */
	public static boolean openFileHandler( final String fname )
	{
	    if ( mAppMain == null ){
	        return false;
	    }
	    return mAppMain.openFile( null, fname );
	}
	


/**
 * @author  okumura
 */
private static class Connect extends Thread
{
	
	/**
	 * Server socket.
	 */
	private ServerSocket mServerSocket = null;


	/**
	 * Main object.
	 */
	private SGMainFunctions mMain;


	/**
	 * Create a thread object with a server socket.
	 * @param main
	 * @param serverSocket
	 */
	private Connect( SGMainFunctions main, ServerSocket serverSocket )
	{
		super();
//System.out.println("Connect");
		this.mMain = main;
		this.mServerSocket = serverSocket;

		this.start();
	}
	

	/**
	 * 
	 */
	public void run()
	{
		//
		// infinite loop as a server process
		//

		BufferedReader br
			= new BufferedReader(
				new InputStreamReader( System.in ) );

//System.out.println("run");
//JOptionPane.showMessageDialog(null,"run");

		BufferedWriter bw
			= new BufferedWriter(
				new OutputStreamWriter( System.out ) );

		try
		{
			while( true )
			{
				String line = br.readLine();
				if( line==null )
				{
					continue;
				}

//				StringTokenizer st = new StringTokenizer(line);
//				ArrayList list = new ArrayList();
//				while( st.hasMoreTokens() )
//				{
//					list.add( st.nextToken() );
//				}
//				String[] array = new String[list.size()];
//				for( int ii=0; ii<array.length; ii++ )
//				{
//					array[ii] = (String)list.get(ii);
//				}
//
//				final boolean ret = this.mMain.executeCommand(array);

				final int ret = this.mMain.exec( line );
				String status = Integer.toString(ret) + "\n";
				bw.write( status );
				bw.flush();
			}
		}
		catch( IOException ex )
		{
			ex.printStackTrace();
			return;
		}



//		while( true )
//		{
//			try
//			{
//				Socket socket = mServerSocket.accept();
//
//				PrintWriter out = new PrintWriter( socket.getOutputStream(), true );
//
//				BufferedReader in = new BufferedReader(
//					new InputStreamReader( socket.getInputStream() ) );
//
//				ArrayList commandList = new ArrayList();
//				String inputLine;
//				while( (inputLine = in.readLine()) != null )
//				{
//					commandList.add( new String( inputLine ) );
//				}
//				if( commandList.size() == 0 )
//				{
//					continue;
//				}
//				String[] commandArray = new String[commandList.size()];
//				for( int ii=0; ii<commandArray.length; ii++ )
//				{
//					commandArray[ii] = (String)commandList.get(ii);
//				}
//
//				if( this.mMain.executeCommand(commandArray) == false )
//				{
//					continue;
//				}
//
//				in.close();
//				out.close();
//
//				socket.close();
//
//			}
//			catch( IOException ex )
//			{
//				ex.printStackTrace();
//			}
//		}
			
	}

}


}

