package usda.weru.util.gis;

import java.awt.Polygon;
import java.awt.geom.Point2D;
import java.io.DataInputStream;
import java.io.IOException;
import org.apache.log4j.Logger;

/**
 *
 * @author wjr
 */
public class HoleyPolygon extends Polygon {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = Logger.getLogger(HoleyPolygon.class);
    Box mbr = null;
    int numParts;
    int numPoints;
    int[] parts = null;
    Point2D.Double[] points = null;
    Polygon[] polygons = null;
    private String dbfStr = null;

    /**
     *
     */
    public static final int degreeMultiplier = 100000;

    HoleyPolygon() {
        super();
    }

    HoleyPolygon(DataInputStream in) throws IOException {
        super();
        read(in);
    }

    /**
     *
     * @param dbf
     * @param dbfStr
     */
    public void setDBFStr(ReadDBFFile dbf, String dbfStr) {
        this.dbfStr = dbfStr;
        String[] dbfFields = dbfStr.split("\\|", -1);
        int stateIndex = dbf.getHeaderIndex("ST");
        if (stateIndex > -1) {
            state = dbfFields[stateIndex].trim();
        } else {
            LOGGER.warn("ST not in dbf record.");
        }

        int stattionIndex = dbf.getHeaderIndex("NAME");
        if (stattionIndex > -1) {
            station = dbfFields[stattionIndex].trim();
        } else {
            LOGGER.warn("NAME not in dbf record.");
        }

        int latIndex = dbf.getHeaderIndex("LAT_DD");
        int lonIndex = dbf.getHeaderIndex("LAT_DD");

        if (latIndex > -1 && lonIndex > -1) {
            double lat = Double.parseDouble(dbfFields[latIndex].trim());
            double lon = Double.parseDouble(dbfFields[lonIndex].trim());
            latLon = new Point2D.Double(lat, lon);
        } else {
            LOGGER.warn("Missing components. Unable to create latlon record");
        }
    }

    private String state = null;

    /**
     *
     * @return
     */
    public String getState() {
        return state;
    }
    private String station = null;

    /**
     *
     * @return
     */
    public String getStation() {
        return station;
    }
    private Point2D latLon = null;

    /**
     *
     * @return
     */
    public Point2D getStationLatLon() {
        return latLon;
    }

    /**
     *
     * @param x
     * @param y
     * @return
     */
    public boolean containsLatLon(double x, double y) {
        int xI = (int) (x * degreeMultiplier);
        int yI = (int) (y * degreeMultiplier);
        return contains(xI, yI);
    }

    void read(DataInputStream in) throws IOException {
        mbr = new Box(in);
        numParts = Swab.swab(in.readInt());
        numPoints = Swab.swab(in.readInt());
        parts = new int[numParts + 1];
        for (int idx = 0; idx < numParts; idx++) {
            parts[idx] = Swab.swab(in.readInt());
        }
        parts[numParts] = numPoints;
        points = new Point2D.Double[numPoints];
        for (int idx = 0; idx < numPoints; idx++) {
            points[idx] = new Point2D.Double();
            points[idx].x = Swab.swab(in.readDouble()) * degreeMultiplier;
            points[idx].y = Swab.swab(in.readDouble()) * degreeMultiplier;
        }
        polygons = new Polygon[numParts];
        int pdx = 0;
        for (int idx = 0; idx < numParts; idx++) {
            polygons[idx] = new Polygon();
            for (; pdx < parts[idx + 1]; pdx++) {
                polygons[idx].addPoint((int) points[pdx].x, (int) points[pdx].y);
                if (idx == 0) {
                    this.addPoint((int) points[pdx].x, (int) points[pdx].y);
                }
            }
        }
    }

    /**
     *
     * @return
     */
    @Override
    public String toString() {
        String partsStr = "parts start ";
        for (int part : parts) {
            partsStr += " " + part;
        }
//        return "parts " + numParts + " points " + numPoints + " " + partsStr;
        return "parts " + numParts + " points " + numPoints + " " + dbfStr;
    }
}
