/*
 * Map.java
 *
 * Created on June 24, 2008, 9:37 AM
 */
package surface;

import hu.swankey.ammo.common.yggdrasil.basics.ComplexObject;
import hu.swankey.ammo.common.yggdrasil.basics.IntegerField;
import hu.swankey.ammo.common.yggdrasil.basics.YContainer;
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.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.ImageIcon;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;

import background.Controller;
import client_engine.IClientControllerListener;

/**
 *
 * @author  solusa
 */
public class MapView extends javax.swing.JPanel implements TreeModelListener, IClientControllerListener {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
    private Image imgCharacter = new ImageIcon(getClass().getResource("/icons/user_gray.png")).getImage().getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH);
    private Image imgObject = new ImageIcon(getClass().getResource("/icons/brick.png")).getImage().getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH);
    private static final int GROUND_COLOR = 0x006000;
    private static final String NO_WORLD_SELECTED = "No world selected";
    
    private static final int LIFE_WIDTH = 26;
    private static final int OBJ_WIDTH = 20;
    private TreeModel model;

    private final Controller controller;
    
    private final boolean drawGrid;

    /** Creates new form Map */
    private MapView(Controller controller, boolean drawGrid) {
        this.controller = controller;
        this.drawGrid = drawGrid;
        setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS));
        setBackground( new Color(GROUND_COLOR) );
        addMouseListener( createMouseListenerForMapView() );
    }
    
    public static MapView create(Controller controller, boolean drawGrid){
    	MapView map = new MapView(controller, drawGrid);
    	map.setWorld(controller.getWorld());
    	
    	controller.addListener(map);
    	return map;
    }
    
    
    public void setWorld(World world){
    	if (model != null)
    		model.removeTreeModelListener(this);
    	
    	model = controller.getYggdrasil().getTreeModel( controller.getWorld() );
        model.addTreeModelListener( this );    	
    }



    @Override
    public void paint(Graphics g) {
        super.paint(g);
        
        World world = controller.getWorld();
        if (world == null) {
        	printText(NO_WORLD_SELECTED, 20, 20, Color.red, g);
            return;
        }

        YContainer node = world.getObjectsContainer();
        
        if (controller.getCursor() != null) {
        	g.setColor(Color.orange);
        	g.drawRect(controller.getCursor().width*20, controller.getCursor().height*20, 20, 20);
        }
        
        
        if (drawGrid) {
            g.setColor(Color.gray);
            int size = 80; // TODO: Térkép méretét a modellből leolvasni!
            for(int i=0; i<size; i++) {
                g.drawLine(0,    i*20, 20*size, i*20);
                g.drawLine(i*20, 0,    i*20,    20*size);
            }
        }
        
        for(YObject element: node.getElements()) {

        	ComplexObject o = (ComplexObject)element;
        	
        	int x = ((IntegerField)o.get("coordx")).getValue()*20;
        	int y = ((IntegerField)o.get("coordy")).getValue()*20;

        	
        	if (controller.getSecondaryElement() == o){
        		g.setColor(Color.RED);
        		g.drawRect(x, y, 20, 20);
        	}        	
        	
        	if (controller.getPrimaryElement() == o){
        		g.setColor(Color.GRAY);
        		g.drawRect(x, y, 20, 20);
        	}
        	

          if ( o.getYClass().getName().equals("FieldObject") || o.getYClass().getName().equals("FragileObject")){
        	  printText(element.getName(), x+10, y+30, Color.LIGHT_GRAY, g);
        	  g.drawImage(imgObject, x, y, this);
          } else {
        	  printText(element.getName(), x+10, y+30, Color.YELLOW, g);
        	  g.drawImage(imgCharacter, x, y, this);
          }
        	
        	
//            g.setFont( g.getFont().deriveFont(Font.BOLD) );            
//            g.setFont( g.getFont().deriveFont( new Float(11) ) );
//            g.setColor( Color.BLACK );
//            g.drawString(element.getName(), x+1+10, y+30-1);        	        	
//        	
//
//            if (o.getYClass().getName().equals("FieldObject") ||
//                o.getYClass().getName().equals("FragileObject")) {
//                g.drawImage(imgObject, x, y, this);
//                g.setColor( Color.LIGHT_GRAY );    
//            } else {
//                g.drawImage(imgCharacter, x, y, this);
//                g.setColor( Color.YELLOW );
//            }

            
//            g.drawString(element.getName(), x+10, y+30-2);
            
            
            // Életerő sáv:
            
            IntegerField lifeField = (IntegerField)o.get("life");
            if (lifeField != null) {
            	int life = lifeField.getValue();
            	if (life < 0) life = 0;
            	if (life > 100) life = 100;
            
            	int life_pixel =  Math.round( new Float((LIFE_WIDTH/100.0)*life ) );
            
            	g.setColor(Color.BLACK);
            	g.drawRect(x-4, y-5, 26, 3);
            	g.setColor(Color.RED);
            	g.fillRect(x- (LIFE_WIDTH - OBJ_WIDTH) / 2, y-4, life_pixel-1, 2);
            }
        }
    }
    
    private void printText(String text, int x, int y, Color color, Graphics g){
    	
        g.setFont( g.getFont().deriveFont(Font.BOLD) );            
        g.setFont( g.getFont().deriveFont( new Float(11) ) );

    	// Shadow:
        g.setColor( Color.BLACK );
        g.drawString(text, x+1, y+1);
    	
        //Text:
        g.setColor( color );
        g.drawString(text, x, y);
    }
    
    private ComplexObject getObjectAt(int coordX, int coordY){
    	YContainer objs = (YContainer)controller.getWorld().get("objects");
    	for(YObject e: objs.getElements()){
    		ComplexObject c = (ComplexObject) e;
    		int x = ((IntegerField)c.get("coordx")).getValue();
    		int y = ((IntegerField)c.get("coordy")).getValue();
    		if ( x == coordX && y == coordY )
    			return c;
    	}
    	return null;
    }
    
    
    private MouseListener createMouseListenerForMapView(){
    	return new MouseListener() {
		
			@Override
			public void mouseReleased(MouseEvent e) {
			}
		
			@Override
			public void mousePressed(MouseEvent e) {
				int coordX = e.getX() / 20;
				int coordY = e.getY() / 20;
				ComplexObject selected = getObjectAt(coordX, coordY);
				
				
				if (e.getButton() == MouseEvent.BUTTON3) {
					controller.setCursor( null );
					if (selected == null) {
						//controller.setSecondaryElement( null );
						controller.setSecondaryElement( controller.getWorld() );
						controller.setPrimaryElement( controller.getWorld() );
					}
					else
						controller.setPrimaryElement( selected );
				} else {					
					if (selected == null) {
						controller.setCursor( new Dimension(coordX, coordY) );
						if (!controller.getWorld().getObjectsContainer().containsValue(controller.getPrimaryElement()))
							controller.setPrimaryElement(controller.getWorld());	
					} else {
						controller.setSecondaryElement( selected );
						//controller.setCursor(null);
					}
					
				}
			}
		
			@Override
			public void mouseExited(MouseEvent e) {
			}
		
			@Override
			public void mouseEntered(MouseEvent e) {
			}
		
			@Override
			public void mouseClicked(MouseEvent e) {
			}
		}; 
    }
    
    

	@Override
	public void treeNodesChanged(TreeModelEvent e) {
		this.updateUI();
	}

	@Override
	public void treeNodesInserted(TreeModelEvent e) {
		this.updateUI();
		
	}

	@Override
	public void treeNodesRemoved(TreeModelEvent e) {
		this.updateUI();
	}

	@Override
	public void treeStructureChanged(TreeModelEvent e) {
		this.updateUI();
	}

	@Override
	public void primaryElementChanged(YObject newElement) {
		this.updateUI();
	}

	@Override
	public void secondaryElementChanged(YObject newElement) {
		this.updateUI();
	}

	@Override
	public void selectedWorldChanged(World world) {
		this.updateUI();
	}

	@Override
	public void cursorChanged(Dimension cursor) {
		this.updateUI();
	}

	@Override
	public void selectedUniverseChanged(Universe universe) {
		// TODO Auto-generated method stub
		
	}    

}
