import java.util.*;
import java.awt.*;
import java.util.concurrent.atomic.*;

public class MyPolygon implements Runnable {
	// ?
	public AtomicInteger vx = new AtomicInteger();
	public AtomicInteger vy = new AtomicInteger();
	public AtomicInteger pp = new AtomicInteger(0);
	Random rnd = new Random();
	
	public AtomicInteger isColors = new AtomicInteger(0);
	
	public ArrayList<Color> colors = new ArrayList<Color>();
	
	public boolean isLife=true;
	Thread t;
	int pCount;
	// точки полигона
	public ArrayList<PointXY> points;
	// точки полигона для вывода на экран с поворотом
	public ArrayList<PointXY> drawPoints;
	
	public Color color;
	
	// координаты полигона, т.е. его центра вращения
	public int x;
	public int y;
	
	// окно
	int WinX=1000, WinY=600;
	
	public int SpeedX;
	public int SpeedY;
	public int SRotate;
	public int CRotate;
	public MyPolygon () {
		colors.add(Color.red);
		colors.add(Color.black);
		colors.add(Color.yellow);
		colors.add(Color.green);
		colors.add(Color.orange);
		colors.add(Color.magenta);
		colors.add(Color.blue);
		colors.add(Color.cyan);
		colors.add(Color.pink);
		
		
		points = new ArrayList<PointXY>();
		drawPoints = new ArrayList<PointXY>();
//		создание потока
		t = new Thread(this,"Polygon");
		//запуск потока
		t.start();	
	}
	
	public int getCRotate() {
		return CRotate;
	}
	public void setCRotate(int rotate) {
		CRotate = rotate;
	}
	public int getSpeedX() {
		return SpeedX;
	}
	public void setSpeedX(int speedX) {
		SpeedX = speedX;
	}
	public int getSpeedY() {
		return SpeedY;
	}
	public void setSpeedY(int speedY) {
		SpeedY = speedY;
	}
	public int getSRotate() {
		return SRotate;
	}
	public void setSRotate(int rotate) {
		SRotate = rotate;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	// Добавляет в коллекцию новую точку.
	public void addPoint(int x, int y, Color color) {
		points.add( new PointXY(x,y,color));
		drawPoints.add( new PointXY(x,y,color));
		pCount++;
	}
	// Удаляет точку по номеру
	public void deletePoint(int ID){
		points.remove(ID);
		drawPoints.remove(ID);
		pCount--;
	}
	// Возвращает истину если точка x,y находиться внутри полигона (смотрим по реальным коорд.)
	public boolean isPointInPolygon (int x, int y) {
		int cp=0,cm=0;
		int d=0;
		// Возьмем первую точку и добавим в конец
		int xa = drawPoints.get(0).getX();
		int ya = drawPoints.get(0).getY();
		drawPoints.add(new PointXY(xa,ya,Color.black));
		xa+=this.x;
		ya+=this.y;
		// Теперь последняя точка повторяет первую, и можно сделать замкнутый цикл по всем точкам...
		// Получим коорд. i-ой точки
		int xi = this.x + drawPoints.get(0).getX();
		int yi = this.y + drawPoints.get(0).getY();
		int i=1;
		do {			
			// получим координаты i-ой и i+1-ой точек
			int xip1 = this.x + drawPoints.get(i).getX();
			int yip1 = this.y + drawPoints.get(i).getY();
			// имеем коорд. i-ой(xi,yi) и i+1(xip1,yip1)
			//System.out.println(i+"-ая точка, d = "+d);
			//System.out.println(xi+" "+yi);
			//System.out.println(xip1+" "+yip1);			
			d = xi*y+x*yip1+xip1*yi-xip1*y-x*yi-xi*yip1;
			if (d > 0) {
				cp++;
			} else {
				cm++;
			}
			xi = this.x + drawPoints.get(i).getX();
			yi = this.y + drawPoints.get(i).getY();
			i++;
		} while (i<drawPoints.size());
		//System.out.println("cm = "+cm+" cp="+cp);
		drawPoints.remove(drawPoints.size()-1);
		return ((cp==drawPoints.size())|(cm==drawPoints.size()));
	}
	public void draw(Graphics g) {
		int i=0;
		g.setColor(color);
		if (drawPoints.size()>0) {
			for (; i< drawPoints.size()-1; i++){
				g.drawLine(x+drawPoints.get(i).getX(), y-drawPoints.get(i).getY(), x+drawPoints.get(i+1).getX(), y-drawPoints.get(i+1).getY());
			}
			g.drawLine(x+drawPoints.get(i).getX(),y- drawPoints.get(i).getY(),x+ drawPoints.get(0).getX(), y-drawPoints.get(0).getY());
		}
	}
	public void calcDraw () {
		for (int i=0; i<drawPoints.size(); i++) {
			double x = points.get(i).getX();
			double y = points.get(i).getY();
			double r = Math.sqrt( x*x + y*y);
			
			double PIDiv180 = 0.017453292519943295769236907684886;
			double SinVal,CosVal, RotAng, Nx, Ny;
			
	//		System.out.println(this.CRotate);
			
			RotAng = this.CRotate * PIDiv180;
			SinVal = Math.sin(RotAng);
			CosVal = Math.cos(RotAng);
			Nx = x * CosVal - y * SinVal;
			Ny = y * CosVal + x * SinVal;
			
			//System.out.println(Nx);
			//System.out.println(Ny);
			
			drawPoints.get(i).setX((int)Math.round(Nx));
			drawPoints.get(i).setY((int)Math.round(Ny));
			//System.out.println(drawPoints.get(i).getX());
			//System.out.println(drawPoints.get(i).getY());
		}
	}
	public boolean isAccessMove () {
		for (int i=0; i < drawPoints.size()-1; i++) {
			if ((drawPoints.get(i).getX()+this.x > WinX-10)|(drawPoints.get(i).getX()+this.x < 10))  {SpeedX=-SpeedX;}
			if ((drawPoints.get(i).getY()+this.y > WinY-10)|(drawPoints.get(i).getY()+this.y < 10))  {SpeedY=-SpeedY;}
		}
		return false;
	}
	// 2 точки лежат с одной стороны от прямой
	public boolean IsPointsOnOneSide(int x1,int y1, int x2, int y2, int xL1, int yL1, int xL2, int yL2) {
		if ((xL1<xL2) | (xL1>xL2)) {
			return ((y1-yL1+(yL1-yL2)*(x1-xL1)/(xL2-xL1))*(y2-yL1+(yL1-yL2)*(x2-xL1)/(xL2-xL1))>=0);
		} else {
			return ((x1-xL1)*(x2-xL2)>=0);
		}
	}
	public boolean isPolygonConvex () {
		boolean Result = true;
		int i=0,j,k;
//		 Возьмем первую точку и добавим в конец
		int xa = drawPoints.get(0).getX();
		int ya = drawPoints.get(0).getY();
		drawPoints.add(new PointXY(xa,ya,Color.black));
	    do {
	        j = 0;
	        do {
	            if ((j!=i) & (j!=i+1)) {
	                k = j+1;
	                do {
	                    if ((k!=i)&(k!=i+1)) { Result = Result & IsPointsOnOneSide(
	                    		drawPoints.get(k).getX(),
	                    		drawPoints.get(k).getY(),
	                    		drawPoints.get(j).getX(),
	                    		drawPoints.get(j).getY(),
	                    		drawPoints.get(i).getX(),
	                    		drawPoints.get(i).getY(),
	                    		drawPoints.get(i+1).getX(),
	                    		drawPoints.get(i+1).getY()  );}
	                    k++;
	                } while ((k<=drawPoints.size()-1) & Result);
	            }
	            j++;
	        } while ((j<=drawPoints.size()-2) & Result);
	        i++;
	    } while ((i<=drawPoints.size()-2) & Result);
	    drawPoints.remove(drawPoints.size()-1);
		return Result;
	}
	public void run() {
		try {
			// описание поведения объекта
			while (isLife) {
				// ATOMIC
				/*int v;
		        do {
		            v = vx.get();
		        } while (!vx.compareAndSet(v, this.x));
		        do {
		            v = vy.get();
		        } while (!vy.compareAndSet(v, this.y));
		        */
				int v= isColors.get();
				
				if (v!=0) {
					color = colors.get(rnd.nextInt(7));
				}
				CRotate = CRotate+ SRotate;
				this.x = this.x + this.SpeedX;
				this.y = this.y + this.SpeedY;
				isAccessMove ();
				calcDraw();
				Thread.sleep(1000);
				
			}
		} catch (InterruptedException e) {
			//System.out.println("Interrupt");
		}
		//System.out.println("Halt");
	}

}