package mior.view;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;

import javax.swing.JPanel;

import mior.model.IMiorModel;
import mior.model.IMiorUpdateListener;
import mior.model.MiorMM;
import mior.model.MiorOM;
import mior.model.MiorWorld;


public class MiorCanvas extends JPanel implements IMiorUpdateListener {
	
	private static final long serialVersionUID = 1L;
	private IMiorModel model;
	
	private final Color BG_COLOR = Color.BLACK;
	private final Color OM_COLOR = new Color(172, 0, 223);
	private final Color MM_ACTIVE_COLOR = Color.WHITE;
	private final Color MM_PASSIVE_COLOR = Color.LIGHT_GRAY;
	private final Color ASSOCIATIONS_COLOR = Color.YELLOW;
	
	private boolean radiusVisible;
	private boolean associationsVisible;
	
	public MiorCanvas(IMiorModel model) {
		this.model = model;
		model.addUpdateListener(this);
		
		radiusVisible = false;
		associationsVisible = true;
		setBackground(BG_COLOR);
		
		// Enable double buffering
		setDoubleBuffered(true);
	}
	
	public IMiorModel getModel() {
		return model;
	}
	
	public void setRadiusVisible(boolean radiusVisible) {
		if (this.radiusVisible != radiusVisible) {
			this.radiusVisible = radiusVisible;
			repaint();
		}
	}
	
	public boolean isRadiusVisible() {
		return radiusVisible;
	}
	
	public void setAssociationsVisible(boolean associationsVisible) {
		if (this.associationsVisible != associationsVisible) {
			this.associationsVisible = associationsVisible;
			System.out.println("repaint");
			repaint();
		}
	}
	
	public boolean isAssociationsVisible() {
		return associationsVisible;
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		if (model == null) {
			return;
		}
		
		Graphics2D g2d = (Graphics2D) g;
		
		// Enable antialiasing
	    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
	                         RenderingHints.VALUE_ANTIALIAS_ON);
	    
	    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
	    		             RenderingHints.VALUE_INTERPOLATION_BICUBIC); 
		
	    MiorWorld world = model.getWorld();
	    
	    g2d.setStroke(new BasicStroke(2.0f));
	    
	    double xScale = 1.0 * getWidth() / world.width;
		double yScale = 1.0 * getHeight() / world.width;
		
		g2d.scale(xScale, yScale);
		
		MiorMM[] mmList = model.getMMList();
		MiorOM[] omList = model.getOMList();
		
		//int [] associations = model.getAssociations();
		
		//System.out.println(Arrays.toString(mmList));
		//System.out.println(Arrays.toString(omList));
		//System.out.println(Arrays.toString(associations));
		
		if (associationsVisible) {
			g2d.setColor(ASSOCIATIONS_COLOR);
			g2d.setStroke(new BasicStroke((float) (1.0f / xScale)));
			
			for (int i = 0; i < mmList.length; i++) {
				for (int j = 0; j < omList.length; j++) {
					
					if (model.isAccessible(i, j)) {
						MiorMM from = mmList[i];
						MiorOM to   = omList[j];
						
						g2d.draw(new Line2D.Double(from.getX(), from.getY(), to.getX(), to.getY()));
					}
				}
			}
			
			g2d.setStroke(new BasicStroke(2.0f));
			
			/*
			for (int i = 0; i < associations.length; i++) {
				int iMM = i / omList.length;
				int iOM = i % omList.length;
				//System.out.println("len: " + mmList.length + ", i: " + i + ", iMM" + iMM + ", iOM: " + iOM);
				
				if (associations[i] != -1) {
					MiorMM from = mmList[iMM];
					MiorOM to   = omList[iOM];
					
					g2d.draw(new Line2D.Double(from.getX(), from.getY(), to.getX(), to.getY()));
				}
			}*/
		}
		
		g2d.setColor(OM_COLOR);
		
		for (MiorOM om : omList) {
			double size = om.getCarbone() / 5000.0;
			double x = om.getX() - size / 2;
			double y = om.getY() - size / 2;
			
			Shape shape = new Ellipse2D.Double(x, y, size, size);
			g2d.fill(shape);
		}
		
		for (MiorMM mm : mmList) {
			double size = mm.getCarbone() / 5000.0;
			double x = mm.getX() - size / 2;
			double y = mm.getY() - size / 2;
			
			Shape shape = new Ellipse2D.Double(x, y, size, size);
			
			if (mm.dormance != 0) {
				g2d.setColor(MM_PASSIVE_COLOR);
			} else {
				g2d.setColor(MM_ACTIVE_COLOR);	
			}
			
			g2d.fill(shape);
			
			if (radiusVisible) {
				double rx = mm.getX() - world.RA;
				double ry = mm.getY() - world.RA;
				Shape radius = new Ellipse2D.Double(rx, ry, 2 * world.RA, 2 * world.RA);
				g2d.draw(radius);
			}
		}
		
	}
	
	@Override
	public Dimension getPreferredSize() {
		return new Dimension(900, 900);
	}
	
	@Override
	public void onMiorModelUpdated(IMiorModel model) {
		this.model = model;
		repaint();
	}
	
}
