//-----------------------------------------------------------------------------
//
// $Id: Simulator.java 8 2006-02-01 16:58:12Z jnross $
// $HeadURL: svn+ssh://wopr.csl.mtu.edu/major/jnross/svn_repos/cs4760/TdaSimulator/src/Simulator.java $
//
//-----------------------------------------------------------------------------

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class Simulator extends JFrame{

	private TdaApp app;
	private JPanel appPanel;
	private SimulatorLayoutPanel layoutPanel;
	
    public Simulator(String []args)
    {
    	//setup application
    	String appClassName = args[0];
    	Class appClass = checkAppClass(appClassName);
    	
    	try {
    		Object obj = appClass.newInstance();
    		app = (TdaApp)obj;
    		appPanel = (JPanel)obj;
    		
    	}
    	catch (Exception e)
    	{
    		System.out.println("Instatiation of class \"" + appClassName + "\" failed");
    		System.exit(1);
    	}
    	setupCommon();
    	
    	//setup up main layout
    	String layoutClassName = args[1];
    	Class layoutClass = checkLayoutClass(layoutClassName);
    	try {
    		Object obj = layoutClass.newInstance();
    		layoutPanel = (SimulatorLayoutPanel)obj;
    		
    	}
    	catch (Exception e)
    	{
    		System.out.println("Instatiation of class \"" + layoutClassName + "\" failed");
    		System.exit(1);
    	}
    	setupUsingLayout();
    	
    	//setup addon layouts
    	for (int i = 2; i < args.length; i++)
    	{
    		String addonClassName = args[i];
    		Class addonClass = checkAddonClass(addonClassName);
    		SimulatorAddon addon = null;
    		try {
    			Object obj = addonClass.newInstance();
    			addon = (SimulatorAddon) obj;
    		}catch (Exception e)
        	{
        		System.out.println("Instatiation of class \"" + addonClassName + "\" failed");
        		System.exit(1);
        	}
    		//make sure our app has an interface for the addon.
    		
    		Class appInterface = addon.addonInterface();
    		
    		try {
    			appClass.asSubclass(appInterface);
    			setupAddon(addon);
    		}
    		catch (ClassCastException e)
    		{
    			System.out.println("Application " + appClass.getName() + " does not implement " + appInterface.getName()
    					+ ", addon will not be set up.");
    		}
    			
    	}
        
    }
    
    private Class checkAppClass(String appClassName)
    {
    	Class appClass = null;
    	try
    	{
    		appClass = Class.forName(appClassName);
    	}
    	catch (ClassNotFoundException e)
    	{
    		System.out.println("Application class \"" + appClassName + "\" was not found");
    		System.exit(1);
    	}
    	
    	try 
    	{
    		appClass.asSubclass(JPanel.class);
    	}
    	catch (ClassCastException e)
    	{
    		System.out.println("Application class \"" + appClassName + "\" must extend JPanel");
    		System.exit(1);
    	}
    	
    	try
    	{
    		appClass.asSubclass(TdaApp.class);
    	}
    	catch (ClassCastException e)
    	{
    		System.out.println("Application class \"" + appClassName + "\" must implement TdaApp");
    		System.exit(1);
    	}
    	return appClass;
    	
    }
    
    private Class checkLayoutClass(String layoutClassName)
    {
    	Class layoutClass = null;
    	try
    	{
    		layoutClass = Class.forName(layoutClassName);
    	}
    	catch (ClassNotFoundException e)
    	{
    		System.out.println("Application class \"" + layoutClassName + "\" was not found");
    		System.exit(1);
    	}
    	
    	try 
    	{
    		layoutClass.asSubclass(SimulatorLayoutPanel.class);
    	}
    	catch (ClassCastException e)
    	{
    		System.out.println("Application class \"" + layoutClassName + "\" must extend SimulatorLayoutPanel");
    		System.exit(1);
    	}
    	return layoutClass;
    	
    }
    
    private Class checkAddonClass(String addonClassName)
    {
    	Class addonClass = null;
    	try
    	{
    		addonClass = Class.forName(addonClassName);
    	}
    	catch (ClassNotFoundException e)
    	{
    		System.out.println("Application class \"" + addonClassName + "\" was not found");
    		System.exit(1);
    	}
    	
    	try 
    	{
    		addonClass.asSubclass(SimulatorAddon.class);
    	}
    	catch (ClassCastException e)
    	{
    		System.out.println("Application class \"" + addonClassName + "\" must extend SimulatorAddon");
    		System.exit(1);
    	}
    	return addonClass;
    	
    }
    
    private void setupCommon()
    {
    	setResizable(false);
        setLayout(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
    }
    
    private void setupUsingLayout()
    {
    	Container win = getContentPane();
    	win.add(layoutPanel);
    	
    	layoutPanel.setupDisplay(appPanel, app);
    	layoutPanel.setupButtonListeners(app);
    	
    	
    	Dimension dimLayout = layoutPanel.getSize();
    	layoutPanel.setBounds(0,0, dimLayout.width, dimLayout.height);
    	setSize(dimLayout); 
    	
    	setVisible(true);
    	setLocationRelativeTo(null);  //put the app in the center of the screen
    	
    	Dimension dimWin = getContentPane().getSize();
    	Dimension dimFrame = layoutPanel.getSize();
    	dimFrame.width += dimLayout.width - dimWin.width;
    	dimFrame.height += dimLayout.height - dimWin.height;
    	setVisible(false);
    	setSize(dimFrame);
    	setVisible(true);
    	
    }
    
    private void setupAddon(SimulatorAddon addon)
    {
    	JFrame newFrame = new JFrame();
    	Container win = newFrame.getContentPane();
    	win.add(addon);
    	
    	if (layoutPanel instanceof KeyListener)
    	{
    		addon.addKeyListener((KeyListener)layoutPanel);
    	}
    	addon.setupAddon(app);
    	
    	Dimension dimLayout = addon.getSize();
    	addon.setBounds(0,0, dimLayout.width, dimLayout.height);
    	newFrame.setSize(dimLayout); 
    	
    	newFrame.setVisible(true);
    	
    	Dimension dimWin = newFrame.getContentPane().getSize();
    	Dimension dimFrame = addon.getSize();
    	dimFrame.width += dimLayout.width - dimWin.width;
    	dimFrame.height += dimLayout.height - dimWin.height;
    	newFrame.setVisible(false);
    	newFrame.setSize(dimFrame);
    	newFrame.setVisible(true);
    	
    }
    
    public static void main(String [] args)
    {
    	if (args.length < 2)
    	{
    		System.out.println("usage: java Simulator <application classname> <layout classname> <addon classname>*");
    		System.exit(0);
    	}
    	else
    	{
    		Simulator instance = new Simulator(args);
    	}
    }
    
    
}
