/*
 * 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.
 */
package org.apache.sis.internal.shapefile;

import java.io.*;
import java.nio.ByteOrder;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.sis.feature.DefaultAttributeType;
import org.apache.sis.feature.DefaultFeatureType;
import org.apache.sis.internal.shapefile.jdbc.*;
import org.apache.sis.storage.shapefile.InvalidShapefileFormatException;
import org.apache.sis.storage.shapefile.ShapeTypeEnum;
import org.apache.sis.util.logging.Logging;
import org.opengis.feature.Feature;

import com.esri.core.geometry.*;

/**
 * Reader of a Shapefile Binary content by the way of a {@link java.nio.MappedByteBuffer}
 *
 * @author  Marc Le Bihan
 * @version 0.5
 * @since   0.5
 * @module
 */
public class ShapefileByteReader extends CommonByteReader<InvalidShapefileFormatException, SQLShapefileNotFoundException> {
    /** Name of the Geometry field. */
    private static final String GEOMETRY_NAME = "geometry";

    /** Shapefile descriptor. */
    private ShapefileDescriptor shapefileDescriptor;

    /** Database Field descriptors. */
    private List<DBase3FieldDescriptor> databaseFieldsDescriptors;

    /** Type of the features contained in this shapefile. */
    private DefaultFeatureType featuresType;

    /** Shapefile index. */
    private File shapeFileIndex;

    /** Shapefile indexes (loaded from .SHX file, if any found). */
    private ArrayList<Integer> indexes;

    /** Shapefile records lengths (loaded from .SHX file, if any found). */
    private ArrayList<Integer> recordsLengths;

    /**
     * Construct a shapefile byte reader.
     * @param shapefile Shapefile.
     * @param dbaseFile underlying database file name.
     * @param shapefileIndex Shapefile index, if any. Null else.
     * @throws InvalidShapefileFormatException if the shapefile format is invalid.
     * @throws SQLInvalidDbaseFileFormatException if the database file format is invalid.
     * @throws SQLShapefileNotFoundException if the shapefile has not been found.
     * @throws SQLDbaseFileNotFoundException if the database file has not been found.
     */
    public ShapefileByteReader(File shapefile, File dbaseFile, File shapefileIndex) throws InvalidShapefileFormatException, SQLInvalidDbaseFileFormatException, SQLShapefileNotFoundException, SQLDbaseFileNotFoundException {
        super(shapefile, InvalidShapefileFormatException.class, SQLShapefileNotFoundException.class);
        this.shapeFileIndex = shapefileIndex;

        loadDatabaseFieldDescriptors(dbaseFile);
        loadDescriptor();

        if (this.shapeFileIndex != null) {
            loadShapefileIndexes();
        }

        this.featuresType = getFeatureType(shapefile.getName());
    }

    /**
     * Returns the DBase 3 fields descriptors.
     * @return Fields descriptors.
     */
    public List<DBase3FieldDescriptor> getFieldsDescriptors() {
        return this.databaseFieldsDescriptors;
    }

    /**
     * Returns the shapefile descriptor.
     * @return Shapefile descriptor.
     */
    public ShapefileDescriptor getShapefileDescriptor() {
        return this.shapefileDescriptor;
    }

    /**
     * Returns the type of the features contained in this shapefile.
     * @return Features type.
     */
    public DefaultFeatureType getFeaturesType() {
        return this.featuresType;
    }

    /**
     * Create a feature descriptor.
     * @param name Name of the field.
     * @return The feature type.
     */
    private DefaultFeatureType getFeatureType(final String name) {
        Objects.requireNonNull(name, "The feature name cannot be null.");

        final int n = this.databaseFieldsDescriptors.size();
        final DefaultAttributeType<?>[] attributes = new DefaultAttributeType<?>[n + 1];
        final Map<String, Object> properties = new HashMap<>(4);

        // Load data field.
        for (int i = 0; i < n; i++) {
            properties.put(DefaultAttributeType.NAME_KEY, this.databaseFieldsDescriptors.get(i).getName());
            attributes[i] = new DefaultAttributeType<>(properties, String.class, 1, 1, null);
        }

        // Add geometry field.
        properties.put(DefaultAttributeType.NAME_KEY, GEOMETRY_NAME);
        attributes[n] = new DefaultAttributeType<>(properties, Geometry.class, 1, 1, null);

        // Add name.
        properties.put(DefaultAttributeType.NAME_KEY, name);
        return new DefaultFeatureType(properties, false, null, attributes);
    }

    /**
     * Load shapefile descriptor.
     */
    private void loadDescriptor() {
        this.shapefileDescriptor = new ShapefileDescriptor(getByteBuffer());
    }

    /**
     * Load shapefile indexes.
     * @return true if shapefile indexes has been read,
     * false if none where available or a problem occured.
     */
    private boolean loadShapefileIndexes() {
        if (this.shapeFileIndex == null) {
            return false;
        }

        try(FileInputStream fis = new FileInputStream(this.shapeFileIndex); FileChannel fc = fis.getChannel()) {
            try {
                int fsize = (int)fc.size();
                MappedByteBuffer indexesByteBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fsize);

                // Indexes entries follow.
                this.indexes = new ArrayList<>();
                this.recordsLengths = new ArrayList<>();
                indexesByteBuffer.position(100);
                indexesByteBuffer.order(ByteOrder.BIG_ENDIAN);

                while(indexesByteBuffer.hasRemaining()) {
                    this.indexes.add(indexesByteBuffer.getInt());        // Data offset : the position of the record in the main shapefile, expressed in words (16 bits).
                    this.recordsLengths.add(indexesByteBuffer.getInt()); // Length of this shapefile record.
                }

                log(Level.INFO, "log.index_has_been_read", this.shapeFileIndex.getAbsolutePath(), this.indexes.size(), this.getFile().getAbsolutePath());
                return true;
            }
            catch(IOException e) {
                log(Level.WARNING, "log.invalid_file_content_for_shapefile_index", this.shapeFileIndex.getAbsolutePath(), e.getMessage());
                this.shapeFileIndex = null;
                return false;
            }
        }
        catch(FileNotFoundException e) {
            log(Level.WARNING, "log.no_shapefile_index_found_at_location", this.shapeFileIndex.getAbsolutePath(), this.getFile().getAbsolutePath());
            this.shapeFileIndex = null;
            return false;
        }
        catch(IOException e) {
            log(Level.WARNING, "log.invalid_file_content_for_shapefile_index", this.shapeFileIndex.getAbsolutePath(), e.getMessage());
            this.shapeFileIndex = null;
            return false;
        }
    }

    /**
     * Load database field descriptors.
     * @param dbaseFile Database file.
     * @throws SQLInvalidDbaseFileFormatException if the database format is incorrect.
     * @throws SQLDbaseFileNotFoundException if the database file cannot be found.
     */
    private void loadDatabaseFieldDescriptors(File dbaseFile) throws SQLInvalidDbaseFileFormatException, SQLDbaseFileNotFoundException {
        MappedByteReader databaseReader = null;

        try {
            databaseReader = new MappedByteReader(dbaseFile, null);
            this.databaseFieldsDescriptors = databaseReader.getFieldsDescriptors();
        }
        finally {
            if (databaseReader != null) {
                try {
                    databaseReader.close();
                }
                catch(IOException e) {
                }
            }
        }
    }

    /**
     * Direct access to a feature by its record number.
     * @param recordNumber Record number.
     * @throws SQLNoDirectAccessAvailableException if this shape file doesn't allow direct acces, because it has no index.
     * @throws SQLInvalidRecordNumberForDirectAccessException if the record number asked for is invalid (below the start, after the end).
     */
    public void setRowNum(int recordNumber) throws SQLNoDirectAccessAvailableException, SQLInvalidRecordNumberForDirectAccessException {
        // Check that the asked record number is not before the first.
        if (recordNumber < 1) {
            String message = format(Level.SEVERE, "excp.wrong_direct_access_before_start", recordNumber, getFile().getAbsolutePath());
            throw new SQLInvalidRecordNumberForDirectAccessException(recordNumber, message);
        }

        // Check that the shapefile allows direct access : it won't if it has no index.
        if (this.shapeFileIndex == null) {
            String message = format(Level.SEVERE, "excp.no_direct_access", getFile().getAbsolutePath());
            throw new SQLNoDirectAccessAvailableException(message);
        }

        int position = this.indexes.get(recordNumber - 1) * 2; // Indexes unit are words (16 bits).

        // Check that the asked record number is not after the last.
        if (position >= this.getByteBuffer().capacity()) {
            String message = format(Level.SEVERE, "excp.wrong_direct_access_after_last", recordNumber, getFile().getAbsolutePath());
            throw new SQLInvalidRecordNumberForDirectAccessException(recordNumber, message);
        }

        try {
            getByteBuffer().position(position);
        }
        catch(IllegalArgumentException e) {
            String message = format(Level.SEVERE, "assert.wrong_position", recordNumber, position, getFile().getAbsolutePath(), e.getMessage());
            throw new RuntimeException(message, e);
        }
    }

    /**
     * Complete a feature with shapefile content.
     * @param feature Feature to complete.
     * @throws InvalidShapefileFormatException if a validation problem occurs.
     */
    public void completeFeature(Feature feature) throws InvalidShapefileFormatException {
        // insert points into some type of list
        int RecordNumber = getByteBuffer().getInt();
        @SuppressWarnings("unused")
        int ContentLength = getByteBuffer().getInt();

        getByteBuffer().order(ByteOrder.LITTLE_ENDIAN);
        int iShapeType = getByteBuffer().getInt();

        ShapeTypeEnum type = ShapeTypeEnum.get(iShapeType);

        if (type == null)
            throw new InvalidShapefileFormatException(MessageFormat.format("The shapefile feature type {0} doesn''t match to any known feature type.", this.featuresType));

        switch (type) {
            case Point:
                loadPointFeature(feature);
                break;

            case Polygon:
                loadPolygonFeature(feature);
                break;

            case PolyLine:
                loadPolylineFeature(feature);
                break;

            default:
                throw new InvalidShapefileFormatException("Unsupported shapefile type: " + iShapeType);
        }

        getByteBuffer().order(ByteOrder.BIG_ENDIAN);
    }

    /**
     * Load point feature.
     * @param feature Feature to fill.
     */
    private void loadPointFeature(Feature feature) {
        double x = getByteBuffer().getDouble();
        double y = getByteBuffer().getDouble();
        Point pnt = new Point(x, y);
        feature.setPropertyValue(GEOMETRY_NAME, pnt);
    }

    /**
     * Load polygon feature.
     * @param feature Feature to fill.
     */
    private void loadPolygonFeature(Feature feature) {
        /* double xmin = */getByteBuffer().getDouble();
        /* double ymin = */getByteBuffer().getDouble();
        /* double xmax = */getByteBuffer().getDouble();
        /* double ymax = */getByteBuffer().getDouble();
        int numParts = getByteBuffer().getInt();
        int numPoints = getByteBuffer().getInt();

        Polygon poly;

        // Handle multiple polygon parts.
        if (numParts > 1) {
            Logger log = Logging.getLogger(ShapefileByteReader.class);

            if (log.isLoggable(Level.FINER)) {
                String format = "Polygon with multiple linear rings encountered at position {0,number} with {1,number} parts.";
                String message = MessageFormat.format(format, getByteBuffer().position(), numParts);
                log.finer(message);
            }

            poly = readMultiplePolygonParts(numParts, numPoints);
        }
        else {
            // Polygon with an unique part.
            poly = readUniquePolygonPart(numPoints);
        }

        feature.setPropertyValue(GEOMETRY_NAME, poly);
    }

    /**
     * Read a polygon that has a unique part.
     * @param numPoints Number of the points of the polygon.
     * @return Polygon.
     */
    @Deprecated // As soon as the readMultiplePolygonParts method proofs working well, this readUniquePolygonPart method can be removed and all calls be deferred to readMultiplePolygonParts.
    private Polygon readUniquePolygonPart(int numPoints) {
        /*int part = */ getByteBuffer().getInt();

        Polygon poly = new Polygon();

        // create a line from the points
        double xpnt = getByteBuffer().getDouble();
        double ypnt = getByteBuffer().getDouble();

        poly.startPath(xpnt, ypnt);

        for (int j = 0; j < numPoints - 1; j++) {
            xpnt = getByteBuffer().getDouble();
            ypnt = getByteBuffer().getDouble();
            poly.lineTo(xpnt, ypnt);
        }

        return poly;
    }

    /**
     * Read a polygon that has multiple parts.
     * @param numParts Number of parts of this polygon.
     * @param numPoints Total number of points of this polygon, all parts considered.
     * @return a multiple part polygon.
     */
    private Polygon readMultiplePolygonParts(int numParts, int numPoints) {
        /**
         * From ESRI Specification :
         * Parts : 0 5  (meaning : 0 designs the first v1, 5 designs the first v5 on the points list below).
         * Points : v1 v2 v3 v4 v1 v5 v8 v7 v6 v5
         *
         * POSITION  FIELD       VALUE      TYPE      NUMBER     ORDER
         * Byte 0    Shape Type  5          Integer   1          Little
         * Byte 4    Box         Box        Double    4          Little
         * Byte 36   NumParts    NumParts   Integer   1          Little
         * Byte 40   NumPoints   NumPoints  Integer   1          Little
         * Byte 44   Parts       Parts      Integer   NumParts   Little
         * Byte X    Points      Points     Point     NumPoints  Little
         */
        int[] partsIndexes = new int[numParts];

        // Read all the parts indexes (starting at byte 44).
        for(int index=0; index < numParts; index ++) {
            partsIndexes[index] = getByteBuffer().getInt();
        }

        // Read all the points.
        double[] xPoints = new double[numPoints];
        double[] yPoints = new double[numPoints];

        for(int index=0; index < numPoints; index ++) {
            xPoints[index] = getByteBuffer().getDouble();
            yPoints[index] = getByteBuffer().getDouble();
        }

        // Create the polygon from the points.
        Polygon poly = new Polygon();

        // create a line from the points
        for(int index=0; index < numPoints; index ++) {
            // Check if this index is one that begins a new part.
            boolean newPolygon = false;

            for(int j=0; j < partsIndexes.length; j ++) {
                if (partsIndexes[j] == index) {
                    newPolygon = true;
                    break;
                }
            }

            if (newPolygon) {
                poly.startPath(xPoints[index], yPoints[index]);
            }
            else {
                poly.lineTo(xPoints[index], yPoints[index]);
            }
        }

        return poly;
    }

    /**
     * Load polyline feature.
     * @param feature Feature to fill.
     */
    private void loadPolylineFeature(Feature feature) {
        /* double xmin = */getByteBuffer().getDouble();
        /* double ymin = */getByteBuffer().getDouble();
        /* double xmax = */getByteBuffer().getDouble();
        /* double ymax = */getByteBuffer().getDouble();

        int NumParts = getByteBuffer().getInt();
        int NumPoints = getByteBuffer().getInt();

        int[] NumPartArr = new int[NumParts + 1];

        for (int n = 0; n < NumParts; n++) {
            int idx = getByteBuffer().getInt();
            NumPartArr[n] = idx;
        }
        NumPartArr[NumParts] = NumPoints;

        double xpnt, ypnt;
        Polyline ply = new Polyline();

        for (int m = 0; m < NumParts; m++) {
            xpnt = getByteBuffer().getDouble();
            ypnt = getByteBuffer().getDouble();
            ply.startPath(xpnt, ypnt);

            for (int j = NumPartArr[m]; j < NumPartArr[m + 1] - 1; j++) {
                xpnt = getByteBuffer().getDouble();
                ypnt = getByteBuffer().getDouble();
                ply.lineTo(xpnt, ypnt);
            }
        }

        feature.setPropertyValue(GEOMETRY_NAME, ply);
    }
}
