package A2;

public class TriangleImpl implements Polygon,Triangle {


		 Point points[] = new Point[3];
		Point a;
		Point b;
		Point c;
		
		TriangleImpl(Point a, Point b, Point c){
			
			this.a=a;
			this.b=b;
			this.c=c;
			this.points[0]=a;
			this.points[1]=b;
			this.points[2]=c;
		}
		
		@Override
		public Point[] getPoints() {
			// TODO Auto-generated method stub
			return points.clone();
		}


		
		public int getNumSides() {
			// TODO Auto-generated method stub
			return points.length;
		}

		
		public Point getVertexAverage() {
			// TODO Auto-generated method stub
			double sumOfX =0;
			double sumOfY= 0;
			for (Point p: this.getPoints()){
				sumOfX+=p.getX();
				sumOfY+=p.getY();
			}
			double xCoord = (double) sumOfX/getPoints().length;
			double yCoord = (double) sumOfY/getPoints().length;
			Point vertexAverage= new Point(xCoord,yCoord);
			return vertexAverage;
			
		}

		
		public RectangleImpl getBoundingBox() {
			// TODO Auto-generated method stub
			double maxEx = 0;
			double maxY = 0;
			double minEx = 0;
			double minY = 0;

			for(int i=0; i<points.length; i++){
				double xCoord = points[i].getX();
				double yCoord = points[i].getY();
				
				if(i==0){
					//initializing
					maxEx = xCoord;
					 maxY = yCoord;
					 minEx = xCoord;
					 minY = yCoord;
				}
				if(xCoord> maxEx){
					maxEx = xCoord;
				}
				if(xCoord< minEx){
					minEx = xCoord;
				}
				if(yCoord> maxY){
					maxY = yCoord;
				}
				if(yCoord< minY){
					minY = yCoord;
				}
				
			}
		
			Point bottomLeft = new Point(minEx,minY);
			Point topRight = new Point(maxEx,maxY);
			RectangleImpl boundingBox = new RectangleImpl(bottomLeft,topRight);
			
			return boundingBox;
			
		}

		@Override
		public Point getCentroid() {
			// TODO Auto-generated method stub
			double C_x=0; 
			double C_y=0; 
			
			for(int i=0;i<points.length;i++){
				double currentX= points[i].getX();
				double currentY = points[i].getY();
				
				
				if(i==points.length-1){
					//we've looped around
					C_x += (currentX+points[0].getX())*(currentX*points[0].getY()-currentY*points[0].getX());
					C_y += (currentY+points[0].getY())*(currentX*points[0].getY()-currentY*points[0].getX());
				}else{
					double nextX = points[i+1].getX();
					double nextY = points[i+1].getY();
					C_x += (currentX+nextX)*(currentX*nextY-currentY*nextX);
					C_y += (currentY+nextY)*(currentX*nextY-currentY*nextX);
				}
		
			}
		
			double Area = 1/(6*getSignedArea());
			Point centroid = new Point(Area*C_x,Area*C_y);
			return centroid;

		}

		@Override
		public double getArea() {
			// TODO Auto-generated method stub
			return Math.abs(getSignedArea());
		
		}

		public double getSignedArea() {
			// TODO Auto-generated method stub
			double sum = 0;
			
			
			for(int i=0;i<getPoints().length;i++){
				double x = points[i].getX();
				double y= points[i].getY();
				
				if(i==(points.length-1)){
					sum += (x*points[0].getY())-(y*points[0].getX());
				}else{
				double nextX = points[i+1].getX();
				double nextY = points[i+1].getY();
				sum+=(x*nextY-nextX*y);
				}
				
			}
			
			return sum/2;
		}
		
		@Override
		
		public void move(double dx, double dy) {
			// TODO Auto-generated method stub
		
			for(int i=0;i<points.length;i++){
				points[i]=points[i].translate(dx, dy);
			}
			
			
		}

		@Override
		public void move(Point c) {
			// TODO Auto-generated method stub
		move(c.getX()-getCentroid().getX(),c.getY()-getCentroid().getY());
		}

		@Override
		public void scale(double factor) {
			// TODO Auto-generated method stub
			
			
			
			double currentX = getCentroid().getX();
			double currentY = getCentroid().getY();
			move(new Point(0,0));
			
		
			for(int i=0;i<points.length;i++){
				points[i] = new Point(points[i].getX()*factor,points[i].getY()*factor);
			}
			move(new Point(currentX,currentY));
			
		}



		@Override
		public Category getCategory() {
			// TODO Auto-generated method stub
			double sideA=a.distanceTo(b);
			double sideB=b.distanceTo(c);
			double sideC=c.distanceTo(a);
			
			if(Math.abs(sideA-sideB)<.01&&Math.abs(sideB-sideC)<.01){
				return Category.EQUILATERAL;
			}else if(Math.abs(sideA-sideB)<.01||Math.abs(sideB-sideC)<.01||Math.abs(sideA-sideC)<.01){
				return Category.ISOSCELES;
			}else{
				return Category.SCALENE;
			}
			
			
		}

		@Override
		public boolean isRight() {
			// TODO Auto-generated method stub
			double sideA=a.distanceTo(b);
			double sideB=b.distanceTo(c);
			double sideC=c.distanceTo(a);
			
			if(Math.abs(((sideA*sideA+sideB*sideB)-sideC*sideC))<=.01||Math.abs(((sideA*sideA+sideC*sideC)-sideB*sideB))<=.01||Math.abs(((sideC*sideC+sideB*sideB)-sideA*sideA))<=.01){
				return true;
			}else{
				return false;
			}
		}



		@Override
		public Point getA() {
			// TODO Auto-generated method stub
			return a;
		}



		@Override
		public Point getB() {
			// TODO Auto-generated method stub
			return b;
		}



		@Override
		public Point getC() {
			// TODO Auto-generated method stub
			return c;
		}

	}
