package template;

import java.awt.AWTEvent;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.Hashtable;

import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.MetalTheme;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

import de.cbse.jeasy.JEDialog;
import de.cbse.jeasy.JEGlobal;
import de.cbse.jeasy.JEHttpClient;
import de.cbse.jeasy.JEObject;
import de.cbse.jeasy.JEPanel;
import de.cbse.jeasy.JEStart;
import de.cbse.jeasy.JETabbedPane;
import de.cbse.jeasy.JETree;
import de.cbse.jeasy.JETreeNode;
import de.cbse.jeasy.JEUtil;

public class CallBack extends DefaultJECallBack {
	// public static final String ROOTTREE = JEIds.TR_PROJECTS;
	public static final String METAL = "METAL";
	private static CallBack callBack;
	private String repository; // File to load initial
	/**
	 * Selected treeNode. 
	 */
	private Client client = null;
	private boolean ignoreEvents = false;
	private boolean simulation = true;
	private boolean actionListening = true;

	private CallBack() {}

	public static CallBack getInstance() {
		if (callBack == null) {
			callBack = new CallBack();
		}
		return callBack;
	}


	/**
	 * All events from the swing components like menus, buttons, checkboxes,
	 * datafields are send to this callBack.
	 * 
	 * @param e
	 *            the event send by the component
	 * @param id
	 *            the id of the JEObject
	 * @param idParent
	 *            the id of the JEObject where the component was added
	 */
	public void callBack(AWTEvent e, String id) {
		// System.out.println("CallBack.callBack()"+e+"\n"+id);
		if (id.equals(JEIds.FR_MAIN)) {
			// event before initialisation
			if (client == null)
				return;
			client.frameChanged(e, id);
			return;
		}
		int eid = e.getID();
		if (eid == ActionEvent.ACTION_PERFORMED && isActionListening()) {
			//			System.out.println("CallBack.callBack()" + e + "\n" + id + " Action = " + isActionListening());
		}
		if (eid == WindowEvent.WINDOW_CLOSING && id.equals(JEIds.FR_MAIN)) {
			exitApplication();
		} else if (e instanceof MouseEvent) {
			client.performMouseEvent((MouseEvent) e, id);
		} else if (eid == ActionEvent.ACTION_PERFORMED && isActionListening()) {
			JEObject jeo = JEUtil.getJO(id);
			// System.out.println("CallBack: " + e + "\nid:" + id + " Parent: " + jeo.getParentId());
			if (jeo.getType().equals(JEObject.MENUITEM)) {
				// check for MenuItems
				Method jmethod;
				try {
					jmethod = client.getClass().getMethod(id, new Class[]{});
					jmethod.invoke(client);
				} catch (Exception ex) {
					JEUtil.log('E', "callBack Action_Performed", id, "No method defined for this action ?");
					ex.printStackTrace();
				}
			} else if (jeo.getType().equals(JEObject.DATAFIELD) || jeo.getType().equals(JEObject.COMBOLIST) || jeo.getType().equals(JEObject.COMBOBOX)) {
				// Button Behind
				Method jmethod;
				if (id.endsWith("_id")) {
					client.performId(id);
				} else {
					try {
						jmethod = client.getClass().getMethod(id, new Class[]{});
						jmethod.invoke(client);
					} catch (Exception ex) {
						// no special method so perform it in performId
						client.performId(id);
					}
				}
			} else if (jeo.getType().equals(JEObject.BUTTON)) {
				// System.out.println("CallBack.callBack()"+e+"\n"+id);
				// check for Buttons
				Method jmethod;
				try {
					jmethod = client.getClass().getMethod(id, null);
					if (jmethod == null) {
						JEUtil.log('E', "callBack Action_Performed", id, "No method defined for this action ?");
						return;
					}
					jmethod.invoke(client);
				} catch (Exception ex) {
					JEUtil.log('E', "callBack Action_Performed", id, "Error invoke mehod !");
					// ex.printStackTrace();
				}
			}
		}
	}

	/**
	 * All mouse events from treenodes are send to this callBack.
	 * 
	 * @param AWTEvent
	 *            the event send by the swing component
	 * @param id
	 *            the id of the JEObject
	 * @param dmt
	 *            the DefaultMutableTreeNode clicked on
	 */
	public void callBack(MouseEvent e, String idTree, DefaultMutableTreeNode dmt) {
		//		System.out.println("CallBack.callBack() Tree " + idTree + " Node " + dmt);
	}

	/**
	 * All Selection events from a JETreeNode are send to this callBack
	 * 
	 * @param e
	 *            the TreeSelectionEvent from a TreeNode
	 * @param id
	 *            of the sending JETree
	 * @param idParent
	 *            the id of the JEObject where the component was added
	 * @param selectedItem
	 *            the selected node
	 */
	public void callBack(TreeSelectionEvent e, String id, TreePath tp) {
		//		System.out.println("treeSelectionEvent: " + e + "\nid:" + id + "\nTreePath:" + tp);
		//		System.out.println(tp.getPathComponent(0));
	}

	/**
	 * All returns from JEMethodinvocation will call this method
	 * 
	 * @param xmi
	 *            xmi String that will be invoked or null if nothimg is to do
	 */
	public void callBackInvoke(String xmi) {
	// System.out.println("CallBackInvoke: " + xmi);
	}

	/**
	 * The events from a tabbedpane are send to this callBack.
	 * 
	 * @param e
	 *            the event send when a tabbedpane element is activated
	 * @param id
	 *            the id of the JEObject
	 */
	public void callBack(ChangeEvent e, String id) {
	//		System.out.println("JEDefaultJECallBack.callBack() ChangeEvent: " + id + "\n" + e);
	}

	private void exitApplication() {
		// TODO ask for save changes
		System.exit(0);
	}
	public Client getClient() {
		return client;
	}

	/**
	 * @return
	 */
	public String getRepository() {
		return repository;
	}

	public void initJECallBack() {
		client = new Client();
		StatusBar.setBtMessage(JEIds.BT_SB_MESSAGE);
		StatusBar.setBtStatus(JEIds.BT_SB_STATUS);
		StatusBar.setBtLanguage(JEIds.BT_SB_LANGUAGE);
		StatusBar.setBtNum(JEIds.BT_SB_NUM);
		StatusBar.setBtDateTime(JEIds.BT_SB_DATETIME);
		StatusBar.setLanguage("DE");
		StatusBar.setBtMemory(JEIds.BT_SB_MEMORY);
		((JETree)JEUtil.getJO(JEIds.TR_TEST)).expandAll();
	}

	public boolean isActionListening() {
		return actionListening;
	}

	/**
	 * @return
	 */
	public boolean isIgnoreEvents() {
		return ignoreEvents;
	}

	/**
	 * @return
	 */
	public boolean isSimulation() {
		return simulation;
	}

	public void setActionListening(boolean b) {
		actionListening = b;
	}

	/**
	 * @param ignoreEvents
	 */
	public void setIgnoreEvents(boolean ignoreEvents) {
		this.ignoreEvents = ignoreEvents;
	}

	public void setLookAndFeel(String laF) {
		if (laF == null) {
			// use JGoodies
			try {
				String lafShortName = "PlasticXP";
				//				String lafClassName;
				//				if ("Windows".equalsIgnoreCase(lafShortName)) {
				//					lafClassName = Options.JGOODIES_WINDOWS_NAME;
				//				} else if ("Plastic".equalsIgnoreCase(lafShortName)) {
				//					lafClassName = Options.PLASTIC_NAME;
				//				} else if ("Plastic3D".equalsIgnoreCase(lafShortName)) {
				//					lafClassName = Options.PLASTIC3D_NAME;
				//				} else if ("PlasticXP".equalsIgnoreCase(lafShortName)) {
				//					lafClassName = Options.PLASTICXP_NAME;
				//				} else {
				//					lafClassName = lafShortName;
				//				}
				//				System.out.println("L&f choosen: " + lafClassName);
				//				JGoodiesSettings settings = JGoodiesSettings.createDefault();
				//				settings.setSelectedLookAndFeel(lafClassName);
				//				settings.setSelectedTheme(PlasticLookAndFeel.createMyDefaultTheme());
				//				settings.configureJGoodiesUI();
				//				UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
				//				UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
				//				UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
			} catch (Exception e) {
				e.printStackTrace();
			}
			SwingUtilities.updateComponentTreeUI(JEObject.getRootPane());
		} else if (laF == METAL) {
			try {
				JEStart jeStart = JEStart.getInstance();
				JEGlobal jeglobal = (JEGlobal) JEUtil.getJO(jeStart.getGlobalId());
				MetalTheme mth = jeglobal.getDefaultMetalTheme();
				if (mth != null) {
					MetalLookAndFeel.setCurrentTheme(mth);
					UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
				} else {
					UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
				}
				//				SwingUtilities.updateComponentTreeUI(JEObject.getRootPane());
				//				jeglobal.updateTreeUIAllDL();
			} catch (Exception ex) {
				System.out.println("Failed loading Metal");
				System.out.println(ex);
			}
		}
	}

	/**
	 * @param repository
	 */
	public void setRepository(String repository) {
		this.repository = repository;
	}

	/**
	 * @param simulation
	 */
	public void setSimulation(boolean simulation) {
		this.simulation = simulation;
	}

	private void setStatusleiste(String string) {}

	/**
	 * Get the InputStream for the given resource. 
	 * @param s
	 * @return
	 * @throws FileNotFoundException
	 */
	public InputStream getResource(String s) {
		InputStream in = this.getClass().getResourceAsStream(s);
		if (in == null) {
			try {
				in = new FileInputStream("/Java/eclipseWorkspace/JEasyExample/src/example/de/cbse/example/" + s.substring(s.lastIndexOf("/")));
			} catch (FileNotFoundException e) {
				System.out.println("CallBack.getResource()" + e);
			}
		}
		return in;
	}
}