package gui.render;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import events.EntityDrawboxChangedEvent;
import events.EntityDrawboxChangedListener;
import model.Drawbox;
import model.Entity;
import model.HitboxRectangle;
import model.Point;

public class DrawboxRectengleRenderingFunction implements ShapeRenderingFunction {
	private List<Point> drawboxPoints;
	private List<Point> basePoints;
	Point currentPoint = new Point(0, 0);
	private List<EntityDrawboxChangedListener> listeners = new ArrayList<>();
	Entity entity;
	Logger logger = Logger.getLogger("gui.DrawboxRectangleEditor");
	public DrawboxRectengleRenderingFunction() {

	}
	
	@Override
	public void drawing(Graphics2D g) {
		Drawbox drawbox = entity.getDrawbox();
        drawboxPoints = drawbox.getDrawboxlistPoints();
        basePoints = drawbox.getbaseListPoints();
        logger.finest("drawbox point size: "+ drawboxPoints.size());
        for(Point p: drawboxPoints) 
            logger.finest("DrawBoxPoint: ["+ p.x + ":"+p.y+"]");
        for(Point p: basePoints) 
            logger.finest("BasePoint: ["+ p.x + ":"+p.y+"]");
        
		if(drawboxPoints.size() >= 1 && drawboxPoints.size() < 4) {
			Point lastPoint = drawboxPoints.get(drawboxPoints.size()-1);
			g.drawLine((int)lastPoint.x, (int)lastPoint.y, (int)currentPoint.x, (int)currentPoint.y);
	        for(int i = 0; i < drawboxPoints.size()-1;i++) {
	            int x1 = (int)drawboxPoints.get(i).x;
	            int y1 = (int)drawboxPoints.get(i).y;
	            int x2 = (int)drawboxPoints.get(i+1).x;
	            int y2 = (int)drawboxPoints.get(i+1).y;
	            g.drawLine(x1, y1, x2, y2);
	        }
		} else {
	        for(int i = 0; i < drawboxPoints.size();i++) {
	            int x1 = (int)drawboxPoints.get(i % drawboxPoints.size()).x;
	            int y1 = (int)drawboxPoints.get(i % drawboxPoints.size()).y;
	            int x2 = (int)drawboxPoints.get((i+1) % drawboxPoints.size()).x;
	            int y2 = (int)drawboxPoints.get((i+1) % drawboxPoints.size()).y;
	            g.drawLine(x1, y1, x2, y2);
	        }
//	         ОТРИСОВКА ОСНОВАНИЯ
	        g.setColor(Color.BLUE);
	        for(int i = 0; i < basePoints.size()-1;i++) {
	            int x1 = (int)basePoints.get(i).x;
	            int y1 = (int)basePoints.get(i).y;
	            int x2 = (int)basePoints.get(i+1).x;
	            int y2 = (int)basePoints.get(i+1).y;
	            g.drawLine(x1, y1+3, x2, y2+3);
	        }
		}
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if(drawboxPoints.size() < 4) {
			Point p = new Point(e.getX(), e.getY());
			drawboxPoints.add(p);
			if(drawboxPoints.size() == 4) {
				sortingDrawboxPoints();		
				saveDataInEntity();
				//при выборе 4-й точки и формировании данных drawbox, уведомляем всех подписчит
				if(listeners!=null) {
					notifySubscribers();	
				}
				
			}
		} 
	}


	@Override
	public void mouseMoved(MouseEvent e) {
		currentPoint.x = e.getX();
		currentPoint.y = e.getY();
	}

	/*Точки должны идти в определенном порядке: 
	 * левая верхняя точка, правая верхняя, нижняя правая, нижняя левая;
	 * Обе нижние точки, т.е. 3 и 4 являются основанием - хардкод.
	 * P.s. возможно это не критично, и в сторе предусмотрено, что бы они сортировались,
	 * но на данном этапе на всякий случай стоит так поступить*/
	private void sortingDrawboxPoints() {
		//окей, это написано плохо, но... Похуй, пляшем)
		Collections.sort(
				drawboxPoints,
			    (point1, point2) -> Float.compare(point1.y, point2.y)
			);
		if(drawboxPoints.get(0).x>drawboxPoints.get(1).x) {
			Collections.swap(drawboxPoints, 0, 1);
		}
		if(drawboxPoints.get(2).x<drawboxPoints.get(3).x) {
			Collections.swap(drawboxPoints, 2, 3);
		}
		/*Багтест, проверка очередности построения точек
		 * 
		 * System.out.println("_______________");
		int i = 0;
		for (Point point : drawboxPoints) {
			System.out.println("Point["+i+"]: ("+point.x+" ; "+point.y+");");
			i++;
		}*/
		
		
	}
	
	
	public void subscribe(EntityDrawboxChangedListener listener) {
        listeners.add(listener);
	}
	
	public void unsubscribe(EntityDrawboxChangedListener listener) {
        listeners.remove(listener);
	}
	//
	private void notifySubscribers() {
		for (EntityDrawboxChangedListener listener : listeners) {
			listener.drawboxChanged(
				new EntityDrawboxChangedEvent(entity.getDrawbox(), entity)
			);
		}
	}
	
	
	public void saveDataInEntity() { 
		entity.setDrawbox(new Drawbox(drawboxPoints));
	}
	
	public void setEntityInDrawboxRectengle(Entity e) {
		entity = e;	
	}
	public void functionClearJButton() {
		if(entity != null) {
			entity.getDrawbox().getDrawboxlistPoints().clear();
			entity.getDrawbox().getbaseListPoints().clear();
		}
	}
}
