package gui.render;

import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

import events.EntityHitboxChangedEvent;
import events.EntityHitboxChangedListener;
import model.Entity;
import model.Hitbox;
import model.HitboxRectangle;
import model.Point;

public class HitboxRectengleRenderingFunction implements ShapeRenderingFunction {

	Point firstIsoPoint = null;
	Point currentIsoPoint = new Point(0,0);
	Point firstCartesianPoint = new Point(0,0), currentCartesianPoint = new Point(0,0);
	private List<EntityHitboxChangedListener> listeners = new ArrayList<>();
	Entity entity;
	private List<Point> LocalListPointsIso = new ArrayList<Point>();
	private List<Point> LocalListPointsCartesian = new ArrayList<Point>();
	
	
	public List<Point> getLocalListPointsIso() {
		return LocalListPointsIso;
	}
	
	public List<Point> getLocalListPointsCartesian() {
		return LocalListPointsCartesian;
	}
	
	public void setFirstIsoPointIsNull(){
		firstIsoPoint = null;
	}
	
	@Override
	public void drawing(Graphics2D g) {
		HitboxRectangle nowHitbox = (HitboxRectangle)entity.getHitbox();
		int x1,y1,x2,y2;
		if(nowHitbox.getListPointsIso().size() == 4) {
			drawingLinesFromListPoints(nowHitbox.getListPointsIso(),g);
		}
		if(firstIsoPoint!=null&&nowHitbox.getListPointsIso().size() == 0) {
			drawingLinesFromListPoints(LocalListPointsIso,g);
		}
		
	}
	
	public void drawingLinesFromListPoints(List<Point> listPointsIso, Graphics2D g) {
		int x1,y1,x2,y2;
			int size = listPointsIso.size();
			for(int i = 0; i < size;i++) {
	            x1 = (int)listPointsIso.get(i % size).x;
	            y1 = (int)listPointsIso.get(i % size).y;
	            x2 = (int)listPointsIso.get((i+1) % size).x;
	            y2 = (int)listPointsIso.get((i+1) % size).y;
	            g.drawLine(x1, y1, x2, y2);
	        }
			x1 = (int)listPointsIso.get(0).x;
            y1 = (int)listPointsIso.get(0).y;
            x2 = (int)listPointsIso.get(3).x;
            y2 = (int)listPointsIso.get(3).y;
            g.drawLine(x1, y1, x2, y2);
	}

	@Override
	public void mousePressed(MouseEvent e) {
		//System.out.println("mousePressed");
		//System.out.println("mouseClicked");
		HitboxRectangle nowHitbox = (HitboxRectangle)entity.getHitbox();
		if(nowHitbox.getListPointsIso().size() == 0 && firstIsoPoint == null) {
			initListsPoints();
			firstIsoPoint = new Point(currentIsoPoint.x,currentIsoPoint.y);
			LocalListPointsIso.get(0).setXY(firstIsoPoint.x, firstIsoPoint.y);
			firstCartesianPoint = Hitbox.isometricToCartesian(firstIsoPoint.x, firstIsoPoint.y,firstCartesianPoint);
			LocalListPointsCartesian.get(0).setXY(firstCartesianPoint.x, firstCartesianPoint.y);
			System.out.println("mouseClicked Event 1 TIME: "+LocalTime.now());
		}else if(nowHitbox.getListPointsIso().size() == 0 && firstIsoPoint != null) {
			nowHitbox.getListPointsIso().addAll(LocalListPointsIso);
			nowHitbox.getListPointsCartesian().addAll(LocalListPointsCartesian);
			System.out.println("mouseClicked Event 2 TIME: "+LocalTime.now());
			
			/*
			 * В данном месте при нажатии закрепляющей точки, необходимо вызывать функцию, 
			 * которая будет формировать из текущих декартовых координат: 
			 * 1. Точку старта и ширину с высотой.
			 * 2. Так же необходимо реализовать слушатель сохранения новых хитбоксов в дерево.
			 * 
			 * */
			notifySubscribers();
		}
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		currentIsoPoint.x = e.getX();
		currentIsoPoint.y = e.getY();
		HitboxRectangle nowHitbox = (HitboxRectangle)entity.getHitbox();
		if(entity!=null) {
			if(firstIsoPoint != null && nowHitbox.getListPointsIso().size() == 0) {
				//System.out.println("firstPoint("+firstIsoPoint.x+";"+firstIsoPoint.y+");");
				currentCartesianPoint = Hitbox.isometricToCartesian(currentIsoPoint.x, currentIsoPoint.y, currentCartesianPoint);
				LocalListPointsCartesian.get(0).setXY(firstCartesianPoint.x, firstCartesianPoint.y);
				LocalListPointsCartesian.get(1).setXY(currentCartesianPoint.x, firstCartesianPoint.y);
				LocalListPointsCartesian.get(2).setXY(currentCartesianPoint.x, currentCartesianPoint.y);
				LocalListPointsCartesian.get(3).setXY(firstCartesianPoint.x, currentCartesianPoint.y);
				convertCartesianPointsToIso();
			}
		}
	}

	public void setEntityInHtiboxRectengle(Entity e) {
		entity = e;	
	}

	public void subscribe(EntityHitboxChangedListener listener) {
        listeners.add(listener);
	}
	
	public void unsubscribe(EntityHitboxChangedListener listener) {
        listeners.remove(listener);
	}
	
	private void notifySubscribers() {
		for (EntityHitboxChangedListener listener : listeners) {
			listener.hitboxChanged(
				new EntityHitboxChangedEvent(entity.getHitbox(), entity)
			);
		}
	}
	
	public void initListsPoints() {
		if(LocalListPointsIso.size()<1) {
			for(int i=0;i<4;i++) { 
				LocalListPointsIso.add(new Point(currentIsoPoint.x,currentIsoPoint.y));
			}	
		}
		if(LocalListPointsCartesian.size()<1) {
			for(int i=0;i<4;i++) { 
				LocalListPointsCartesian.add(new Point(0,0));
			}	
		}
	}
	public void convertCartesianPointsToIso() {
		Point cartesianPoint;
		for (int i = 0 ; i<4;i++) {
			cartesianPoint = LocalListPointsCartesian.get(i);
			Hitbox.cartesianToIsometric(cartesianPoint.x,cartesianPoint.y,LocalListPointsIso.get(i));
		}
	}
	
}
