package surface;

import hu.swankey.ammo.common.yggdrasil.basics.IntegerField;
import hu.swankey.ammo.common.yggdrasil.basics.YObject;
import hu.swankey.ammo.common.yggdrasil.ext.Universe;
import hu.swankey.ammo.common.yggdrasil.ext.World;

import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import adapters.ClassTreeModel;
import background.Controller;
import client_engine.ClientController;
import client_engine.IClientControllerListener;


public class SelectorTree extends JPanel implements IClientControllerListener {
	
	private static final long serialVersionUID = 1L;
	private static final String TITLE_POSTFIX = ":";
	
	private final boolean reflectPrimarySelection;
	private final JLabel jlabel_title = new JLabel();
	private final JTree jtree = new JTree();
	private final JScrollPane jscroll_jtree = new JScrollPane(jtree);
	
	
	private SelectorTree( boolean reflectPrimarySelection ) {
		this.reflectPrimarySelection = reflectPrimarySelection;
	}	
	
	
	public static SelectorTree createYggdrasilSelector(String title, YObject root, final Controller controller, final boolean reflectPrimarySelection){
		
		if (root == null)
			throw new NullPointerException("'root' cannot be null");
		
		final SelectorTree st = new SelectorTree(reflectPrimarySelection);
		st.setModel( controller.getYggdrasil().getTreeModel( root ) );
		init(st, title, controller);
		return st;
	}
	
	public static SelectorTree createClassSelector(String title, Controller controller, boolean reflectPrimarySelection){
		
		final SelectorTree st = new SelectorTree(reflectPrimarySelection);
		st.setModel( ClassTreeModel.getClassTreeModelFor(controller.getYggdrasil()) );
		init(st, title, controller);
		return st;
	}	
	
	
	private static void init(final SelectorTree st, String title, final ClientController controller){
		
		// Layout:
		st.setLayout(new BoxLayout(st, BoxLayout.Y_AXIS));
		
		// Title:
		st.jlabel_title.setText(title + TITLE_POSTFIX);
		st.add( st.jlabel_title );
		
		// JTree:
		st.jtree.setCellRenderer(new YggdrasilCellRenderer());
		st.jtree.addTreeSelectionListener(new TreeSelectionListener() {

			@Override
	        public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
	            	
				if (st.jtree.getSelectionPath() != null) {
					YObject selection = (YObject) st.jtree.getSelectionPath().getLastPathComponent();
	                	
	                if (st.reflectPrimarySelection)
	                	controller.setPrimaryElement( selection );
	                else
	                	controller.setSecondaryElement( selection );
	                }
	            }
	        });
		
		st.jtree.addMouseListener( new MouseListener(){

			@Override
			public void mouseReleased(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
				
				if (e.getClickCount() == 2 && st.jtree.getSelectionPath() != null) {
					YObject selection = (YObject) st.jtree.getSelectionPath().getLastPathComponent(

					if (selection instanceof IntegerField) {
						controller.setPrimaryElement( (YObject) st.jtree.getSelectionPath().getLastPathComponent() );
						controller.getCommander().execute("%2 = %I(value);");
						System.out.println("TODO: Parancsokat bevinni Yggdrasil-ba!");
					}

				}
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
			}
		} );
		
		
		// JScrollPane:
		st.jscroll_jtree.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
		st.jscroll_jtree.setAlignmentX(0);
		st.add( st.jscroll_jtree );
			
		
		// Listening:
		controller.addListener(st);
	}



	
	
//	public static JTree createEditorJTree(final ClientAController controller, YObject root, final boolean reflectPrimarySelection){
//		
//		
//		
//		//final JTree jtree = new JTree();
//			
//		//jtree.setModel( controller.getYggdrasil().getTreeModel( root ) );
////		jtree.setCellRenderer(new YggdrasilCellRenderer());
////		jtree.addTreeSelectionListener(new TreeSelectionListener() {
////
////		@Override
////        public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
////            	
////			if (jtree.getSelectionPath() != null) {
////				YObject selection = (YObject) jtree.getSelectionPath().getLastPathComponent();
////                	
////                if (reflectPrimarySelection)
////                	controller.setPrimaryElement( selection );
////                else
////                	controller.setSecondaryElement( selection );
////                }
////            }
////        });		
//		
//		
////		jtree.addMouseListener( new MouseListener(){
////
////			@Override
////			public void mouseReleased(MouseEvent e) {
////			}
////
////			@Override
////			public void mousePressed(MouseEvent e) {
////				
////				if (e.getClickCount() == 2 && jtree.getSelectionPath() != null) {
////					YObject selection = (YObject) jtree.getSelectionPath().getLastPathComponent();
////
////					if (selection instanceof MethodDefinition)
////						ScriptEditor.getScriptEditor((MethodDefinition) selection, controller).setVisible(true);
////
////					if (selection instanceof IntegerField) {
////						controller.setPrimaryElement( (YObject) jtree.getSelectionPath().getLastPathComponent() );
////						controller.getCommander().execute("assign(source:%I(value), target:%2)");
////						System.out.println("TODO: Parancsokat bevinni Yggdrasil-ba!");
////					}
////
////				}
////			}
////
////			@Override
////			public void mouseExited(MouseEvent e) {
////			}
////
////			@Override
////			public void mouseEntered(MouseEvent e) {
////			}
////
////			@Override
////			public void mouseClicked(MouseEvent e) {
////			}
////		} );
//		
//		
//		return jtree;
//	}

	@Override
	public void cursorChanged(Dimension cursor) { }

	@Override
	public void primaryElementChanged(YObject newElement) {		
    	if (reflectPrimarySelection) 
    		setSelection(newElement);
    	
    	
	}

	@Override
	public void secondaryElementChanged(YObject newElement) {
		if (!reflectPrimarySelection) 
    		setSelection(newElement);
	}
	
	private void setSelection(YObject newSelection){
		
    	if (newSelection != null) 
    	{    		
    		List<YObject> path = newSelection.getPathFrom( (YObject)jtree.getModel().getRoot() );
    		if (path != null) {
    			
    			// Check path availability:
    			//YObject node = jtree.getModel().getRoot();
    			int i;
    			for (i=0; i+1 < path.size(); i++)
    				if (jtree.getModel().getIndexOfChild(path.get(i), path.get(i+1)) == -1) break;
    			
    			if (i+1 < path.size()) {
    			//	jtree.clearSelection();
    				jtree.setSelectionPath(null);
    			}
    			else {    				
    				jtree.setSelectionPath( new TreePath( path.toArray()) );
    				jtree.scrollRowToVisible( jtree.getRowForPath(  new TreePath( path.toArray()) ) );
    				// TODO: expandPath
    			}
    		}
    	} else
    		jtree.setSelectionPath(null);
	}

	@Override
	public void selectedWorldChanged(World world) {
		throw new UnsupportedOperationException();
	}
	
	public TreeModel getModel(){
		return jtree.getModel();
	}
	
	public void setModel(TreeModel newModel){
		jtree.setModel(newModel);
	}

	@Override
	public void selectedUniverseChanged(Universe universe) {
		throw new UnsupportedOperationException();
	}
	
	@Override
	public String toString(){
		return jlabel_title.getText();
	}

}