/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * @author Denis M. Kishenko
 * @version $Revision$
 */
package java.awt;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.NoSuchElementException;

import org.apache.harmony.awt.gl.*;
import org.apache.harmony.awt.internal.nls.Messages;

/**
 * The Polygon class defines an closed area specified by n vertices and 
 * n edges. The coordinates of the vertices are specified by x, y arrays.
 * The edges are the line segments from the point (x[i], y[i]) to the point 
 * (x[i+1], y[i+1]), for -1 < i < (n-1) plus the line segment from 
 * the point (x[n-1], y[n-1]) to the point (x[0], y[0]) point. 
 * The Polygon is empty if the number of vertices is zero.   
 */
public class Polygon implements Shape, Serializable {

    /** The Constant serialVersionUID. */
    private static final long serialVersionUID = -6460061437900069969L;

    /** The points buffer capacity. */
    private static final int BUFFER_CAPACITY = 4;
    
    /** The number of Polygon vertices.*/
    public int npoints;
    
    /** The array of X coordinates of the vertices. */
    public int[] xpoints;
    
    /** The array of Y coordinates of the vertices. */
    public int[] ypoints;
    
    /**  
     * The smallest Rectangle that completely contains this Polygon. 
     */
    protected Rectangle bounds;

    /*
     * Polygon path iterator  
     */
    /**
     * The internal Class Iterator.
     */
    class Iterator implements PathIterator {

        /** The source Polygon object. */
        public Polygon p;
        
        /** The path iterator transformation. */
        public AffineTransform t;
        
        /** The current segmenet index. */
        public int index;

        /**
         * Constructs a new Polygon.Iterator for the given polygon and transformation
         * 
         * @param at - the AffineTransform object to apply rectangle path
         * @param p the p
         */
        public Iterator(AffineTransform at, Polygon p) {
            this.p = p;
            this.t = at;
            if (p.npoints == 0) {
                index = 1;
            }
        }

        public int getWindingRule() {
            return WIND_EVEN_ODD;
        }

        public boolean isDone() {
            return index > p.npoints;
        }

        public void next() {
            index++;
        }

        public int currentSegment(double[] coords) {
            if (isDone()) {
                // awt.110=Iterator out of bounds
                throw new NoSuchElementException(Messages.getString("awt.110")); //$NON-NLS-1$
            }
            if (index == p.npoints) {
                return SEG_CLOSE;
            }
            coords[0] = p.xpoints[index];
            coords[1] = p.ypoints[index];
            if (t != null) {
                t.transform(coords, 0, coords, 0, 1);
            }
            return index == 0 ? SEG_MOVETO : SEG_LINETO;
        }

        public int currentSegment(float[] coords) {
            if (isDone()) {
                // awt.110=Iterator out of bounds
                throw new NoSuchElementException(Messages.getString("awt.110")); //$NON-NLS-1$
            }
            if (index == p.npoints) {
                return SEG_CLOSE;
            }
            coords[0] = p.xpoints[index];
            coords[1] = p.ypoints[index];
            if (t != null) {
                t.transform(coords, 0, coords, 0, 1);
            }
            return index == 0 ? SEG_MOVETO : SEG_LINETO;
        }
    }

    /**
     * Instantiates a new empty polygon.
     */
    public Polygon() {
        xpoints = new int[BUFFER_CAPACITY];
        ypoints = new int[BUFFER_CAPACITY];
    }

    /**
     * Instantiates a new polygon with the specified number of vertices,
     * and the given arrays of x, y vertex coordinates. The length of 
     * each coordinate array may not be less than the specified number of 
     * vertices but may be greater. Only the first n elements are used from 
     * each coordinate array.
     * 
     * @param xpoints the array of X vertex coordinates. 
     * @param ypoints the array of Y vertex coordinates.
     * @param npoints the number vertices of the polygon.
     * @throws IndexOutOfBoundsException if the length of xpoints or ypoints
     * is less than n.
     * @throws NegativeArraySizeException if n is negative.
     */
    public Polygon(int[] xpoints, int[] ypoints, int npoints) {
        if (npoints > xpoints.length || npoints > ypoints.length) {
            // awt.111=Parameter npoints is greater than array length
            throw new IndexOutOfBoundsException(Messages.getString("awt.111")); //$NON-NLS-1$
        }
        if (npoints < 0) {
            // awt.112=Negative number of points
            throw new NegativeArraySizeException(Messages.getString("awt.112")); //$NON-NLS-1$
        }
        this.npoints = npoints;
        this.xpoints = new int[npoints];
        this.ypoints = new int[npoints];
        System.arraycopy(xpoints, 0, this.xpoints, 0, npoints);
        System.arraycopy(ypoints, 0, this.ypoints, 0, npoints);
    }

    /**
     * Resets the current Polygon to an empty Polygon. More precisely, 
     * the number of Polygon vertices is set to zero, but x, y coordinates 
     * arrays are not affected.  
     */
    public void reset() {
        npoints = 0;
        bounds = null;
    }

    /**
     * Invalidates the data that depends on the vertex coordinates. 
     * This method should be called after direct manipulations  
     * of the x, y vertex coordinates arrays to avoid unpredictable 
     * results of methods which rely on the bounding box.
     */
    public void invalidate() {
        bounds = null;
    }

    /**
     * Adds the point to the Polygon and updates the bounding box 
     * accordingly.
     * 
     * @param px the X coordinate of the added vertex.
     * @param py the Y coordinate of the added vertex.
     */
    public void addPoint(int px, int py) {
        if (npoints == xpoints.length) {
            int[] tmp;

            tmp = new int[xpoints.length + BUFFER_CAPACITY];
            System.arraycopy(xpoints, 0, tmp, 0, xpoints.length);
            xpoints = tmp;

            tmp = new int[ypoints.length + BUFFER_CAPACITY];
            System.arraycopy(ypoints, 0, tmp, 0, ypoints.length);
            ypoints = tmp;
        }

        xpoints[npoints] = px;
        ypoints[npoints] = py;
        npoints++;

        if (bounds != null) {
            bounds.setFrameFromDiagonal(
                    Math.min(bounds.getMinX(), px),
                    Math.min(bounds.getMinY(), py),
                    Math.max(bounds.getMaxX(), px),
                    Math.max(bounds.getMaxY(), py));
        }
    }

    /**
     * Gets the bounding rectangle of the Polygon. The bounding rectangle
     * is the smallest rectangle which contains the Polygon.
     * 
     * @return the bounding rectangle of the Polygon.
     * 
     * @see java.awt.Shape#getBounds()
     */
    public Rectangle getBounds() {
        if (bounds != null) {
            return bounds;
        }
        if (npoints == 0) {
            return new Rectangle();
        }

        int bx1 = xpoints[0];
        int by1 = ypoints[0];
        int bx2 = bx1;
        int by2 = by1;

        for (int i = 1; i < npoints; i++) {
            int x = xpoints[i];
            int y = ypoints[i];
            if (x < bx1) {
                bx1 = x;
            } else if (x > bx2) {
                bx2 = x;
            }
            if (y < by1) {
                by1 = y;
            } else if (y > by2) {
                by2 = y;
            }
        }

        return bounds = new Rectangle(bx1, by1, bx2 - bx1, by2 - by1);
    }

    /**
     * Gets the bounding rectangle of the Polygon. The bounding rectangle
     * is the smallest rectangle which contains the Polygon.
     * 
     * @return the bounding rectangle of the Polygon.
     * 
     * @deprecated Use getBounds() method.
     */
    @Deprecated
    public Rectangle getBoundingBox() {
        return getBounds();
    }

    /**
     * Gets the Rectangle2D which represents Polygon bounds.
     * The bounding rectangle is the smallest rectangle which contains 
     * the Polygon.
     * 
     * @return the bounding rectangle of the Polygon.
     * 
     * @see java.awt.Shape#getBounds2D()
     */
    public Rectangle2D getBounds2D() {
        return getBounds().getBounds2D();
    }

    /**
     * Translates all vertices of Polygon the specified distances
     * along X, Y axis.
     * 
     * @param mx the distance to translate horizontally.
     * @param my the distance to translate vertically.
     */
    public void translate(int mx, int my) {
        for (int i = 0; i < npoints; i++) {
            xpoints[i] += mx;
            ypoints[i] += my;
        }
        if (bounds != null) {
            bounds.translate(mx, my);
        }
    }

    /**
     * Checks whether or not the point given by the coordinates x, y lies inside 
     * the Polygon.
     * 
     * @param x the X coordinate of the point to check.
     * @param y the Y coordinate of the point to check.
     * 
     * @return true, if the specified point lies inside the Polygon,
     * otherwise false.
     * 
     * @deprecated Use contains(int, int) method.
     */
    @Deprecated
    public boolean inside(int x, int y) {
        return contains((double) x, (double) y);
    }

    /**
     * Checks whether or not the point given by the coordinates x, y lies inside 
     * the Polygon.
     * 
     * @param x the X coordinate of the point to check.
     * @param y the Y coordinate of the point to check.
     * 
     * @return true, if the specified point lies inside the Polygon,
     * otherwise false.
     */
    public boolean contains(int x, int y) {
        return contains((double) x, (double) y);
    }

    /**
     * Checks whether or not the point with specified double coordinates 
     * lies inside the Polygon.
     * 
     * @param x the X coordinate of the point to check.
     * @param y the Y coordinate of the point to check.
     * 
     * @return true, if the point given by the double coordinates 
     * lies inside the Polygon, otherwise false.
     * 
     * @see java.awt.Shape#contains(double, double)
     */
    public boolean contains(double x, double y) {
        return Crossing.isInsideEvenOdd(Crossing.crossShape(this, x, y));
    }

    /**
     * Checks whether or not the rectangle determined by the parameters  
     * [x, y, width, height] lies inside the Polygon.
     * 
     * @param x the X coordinate of the rectangles's left upper 
     * corner as a double.
     * @param y the Y coordinate of the rectangles's left upper 
     * corner as a double.
     * @param width the width of rectangle as a double.
     * @param width the height of rectangle as a double.
     * 
     * @return true, if the specified rectangle lies inside the Polygon,
     * otherwise false.
     * 
     * @see java.awt.Shape#contains(double, double, double, double)
     */
    public boolean contains(double x, double y, double width, double height) {
        int cross = Crossing.intersectShape(this, x, y, width, height);
        return cross != Crossing.CROSSING && Crossing.isInsideEvenOdd(cross);
    }

    /**
     * Checks whether or not the rectangle determined by the parameters  
     * [x, y, width, height] intersects the interior of
     * the Polygon.
     * 
     * @param x the X coordinate of the rectangles's left upper 
     * corner as a double.
     * @param y the Y coordinate of the rectangles's left upper 
     * corner as a double.
     * @param width the width of rectangle as a double.
     * @param width the height of rectangle as a double.
     * 
     * @return true, if the specified rectangle intersects the interior of
     * the Polygon, otherwise false.
     * 
     * @see java.awt.Shape#intersects(double, double, double, double)
     */
    public boolean intersects(double x, double y, double width, double height) {
        int cross = Crossing.intersectShape(this, x, y, width, height);
        return cross == Crossing.CROSSING || Crossing.isInsideEvenOdd(cross);
    }

    /**
     * Checks whether or not the specified rectangle lies inside the Polygon.
     * 
     * @param rect the Rectangle2D object.
     * 
     * @return true, if the specified rectangle lies inside the Polygon,
     * otherwise false.
     * 
     * @see java.awt.Shape#contains(java.awt.geom.Rectangle2D)
     */
    public boolean contains(Rectangle2D rect) {
        return contains(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
    }

    /**
     * Checks whether or not the specified Point lies inside the Polygon.
     * 
     * @param point the Point object.
     * 
     * @return true, if the specified Point lies inside the Polygon,
     * otherwise false.
     */
    public boolean contains(Point point) {
        return contains(point.getX(), point.getY());
    }

    /**
     * Checks whether or not the specified Point2D lies inside the Polygon.
     * 
     * @param point the Point2D object.
     * 
     * @return true, if the specified Point2D lies inside the Polygon,
     * otherwise false.
     * 
     * @see java.awt.Shape#contains(java.awt.geom.Point2D)
     */
    public boolean contains(Point2D point) {
        return contains(point.getX(), point.getY());
    }

    /**
     * Checks whether or not the interior of rectangle specified by 
     * the Rectangle2D object intersects the interior of the Polygon.
     * 
     * @param rect the Rectangle2D object.
     * 
     * @return true, if the Rectangle2D intersects the interior of
     * the Polygon, otherwise false.
     * 
     * @see java.awt.Shape#intersects(java.awt.geom.Rectangle2D)
     */
    public boolean intersects(Rectangle2D rect) {
        return intersects(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
    }

    /**
     * Gets the PathIterator object which gives the coordinates of 
     * the polygon, transformed according to the specified AffineTransform.
     * 
     * @param t the specified AffineTransform object, or null.
     * 
     * @return PathIterator object for the Polygon.
     * 
     * @see java.awt.Shape#getPathIterator(java.awt.geom.AffineTransform)
     */
    public PathIterator getPathIterator(AffineTransform t) {
        return new Iterator(t, this);
    }

    /**
     * Gets the PathIterator object which gives the coordinates of 
     * the polygon, transformed according to the specified AffineTransform.
     * The flatness parameter is ignored.
     * 
     * @param t the specified AffineTransform object, or null.
     * @param flatness the maximum number of the control points for 
     * a given curve which varies from colinear before a subdivided curve 
     * is replaced by a straight line connecting the endpoints. 
     * This parameter is ignored for the Polygon class.
     * 
     * @return PathIterator object for the Polygon.
     *  
     * @see java.awt.Shape#getPathIterator(java.awt.geom.AffineTransform, double)
     */
    public PathIterator getPathIterator(AffineTransform t, double flatness) {
        return new Iterator(t, this);
    }

}

