/*
 * 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.jdbc;

import java.io.File;
import java.nio.BufferUnderflowException;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.*;
import java.util.logging.Level;

import org.apache.sis.internal.shapefile.jdbc.resultset.SQLIllegalColumnIndexException;
import org.apache.sis.internal.shapefile.jdbc.resultset.SQLNoSuchFieldException;
import org.opengis.feature.Feature;


/**
 * Reader of a Database Binary content by the way of a {@link java.nio.MappedByteBuffer}
 *
 * @author  Marc Le Bihan
 * @version 0.5
 * @since   0.5
 * @module
 */
public class MappedByteReader extends AbstractDbase3ByteReader implements AutoCloseable {
    /** List of field descriptors. */
    private List<DBase3FieldDescriptor> fieldsDescriptors = new ArrayList<>();

    /** Connection properties. */
    private Properties info;
    
    /**
     * Construct a mapped byte reader on a file.
     * @param dbase3File File.
     * @param connectionInfos Connection properties, maybe null.
     * @throws SQLInvalidDbaseFileFormatException if the database seems to be invalid.
     * @throws SQLDbaseFileNotFoundException if the Dbase file has not been found.
     */
    public MappedByteReader(File dbase3File, Properties connectionInfos) throws SQLInvalidDbaseFileFormatException, SQLDbaseFileNotFoundException {
        super(dbase3File);
        this.info = connectionInfos;
        
        // React to special features asked.
        if (this.info != null) {
            // Sometimes, DBF files have a wrong charset, or more often : none, and you have to specify it.
            String recordCharset = (String)this.info.get("record_charset");
            
            if (recordCharset != null) {
                Charset cs = Charset.forName(recordCharset);
                setCharset(cs);
            }
        }
        
        loadDescriptor();
    }

    /**
     * Load a row into a feature.
     * @param feature Feature to fill.
     */
    @Override public void loadRowIntoFeature(Feature feature) {
        // TODO: ignore deleted records
        getByteBuffer().get(); // denotes whether deleted or current
        // read first part of record

        for (DBase3FieldDescriptor fd : this.fieldsDescriptors) {
            byte[] data = new byte[fd.getLength()];
            getByteBuffer().get(data);

            int length = data.length;
            while (length != 0 && Byte.toUnsignedInt(data[length - 1]) <= ' ') {
                length--;
            }

            String value = new String(data, 0, length);
            feature.setPropertyValue(fd.getName(), value);
        }
    }

    /**
     * Checks if a next row is available. Warning : it may be a deleted one.
     * @return true if a next row is available.
     */
    @Override
    public boolean nextRowAvailable() {
        // 1) Check for remaining bytes.
        if (getByteBuffer().hasRemaining() == false) {
            return false;
        }
        
        // 2) Check that the immediate next byte read isn't the EOF signal.
        byte eofCheck = getByteBuffer().get();
        
        boolean isEOF = (eofCheck == 0x1A);
        this.log(Level.FINER, "log.delete_status", getRowNum(), eofCheck, isEOF ? "EOF" : "Active");
        
        if (eofCheck == 0x1A) {
            return false;
        }
        else {
            // Return one byte back.
            int position = getByteBuffer().position();
            getByteBuffer().position(position-1);
            return true;
        }
    }

    /**
     * Returns the record number of the last record red.
     * @return The record number.
     */
    @Override public int getRowNum() {
        int position = getByteBuffer().position();
        int recordNumber = (position - Short.toUnsignedInt(this.firstRecordPosition)) / Short.toUnsignedInt(this.recordLength);
        return recordNumber;
    }

    /**
     * Read the next row as a set of objects.
     * @return Map of field name / object value.
     */
    @Override
    public Map<String, byte[]> readNextRowAsObjects() {
        // TODO: ignore deleted records
        /* byte isDeleted = */ getByteBuffer().get(); // denotes whether deleted or current
        
        // read first part of record
        HashMap<String, byte[]> fieldsValues = new HashMap<>();

        for (DBase3FieldDescriptor fd : this.fieldsDescriptors) {
            byte[] data = new byte[fd.getLength()];
            getByteBuffer().get(data);

            // Trim the bytes right.
            int length = data.length;
            
            while (length != 0 && Byte.toUnsignedInt(data[length - 1]) <= ' ') {
                length--;
            }
            
            if (length != data.length) {
                byte[] dataTrimmed = new byte[length];
                
                for(int index=0; index < length; index ++) {
                    dataTrimmed[index] = data[index];
                }
                
                fieldsValues.put(fd.getName(), dataTrimmed);
            }
            else {
                fieldsValues.put(fd.getName(), data);
            }
        }

        return fieldsValues;
    }

    /**
     * Loading the database file content from binary .dbf file.
     * @throws SQLInvalidDbaseFileFormatException if descriptor is not readable.
     */
    private void loadDescriptor() throws SQLInvalidDbaseFileFormatException {
        try {
            this.dbaseVersion = getByteBuffer().get();
            getByteBuffer().get(this.dbaseLastUpdate);

            getByteBuffer().order(ByteOrder.LITTLE_ENDIAN);
            this.rowCount = getByteBuffer().getInt();
            this.firstRecordPosition = getByteBuffer().getShort();
            this.recordLength = getByteBuffer().getShort();
            getByteBuffer().order(ByteOrder.BIG_ENDIAN);

            getByteBuffer().get(this.reservedFiller1);
            this.reservedIncompleteTransaction = getByteBuffer().get();
            this.reservedEncryptionFlag = getByteBuffer().get();
            getByteBuffer().get(this.reservedFreeRecordThread);
            getByteBuffer().get(this.reservedMultiUser);
            this.reservedMDXFlag = getByteBuffer().get();

            // Translate code page value to a known charset.
            this.codePage = getByteBuffer().get();
            
            if (this.charset == null) {
                try {
                    this.charset = toCharset(this.codePage);
                }
                catch(UnsupportedCharsetException e) {
                    // Warn the caller that he will have to perform is own conversions.
                    log(Level.WARNING, "log.no_valid_charset", getFile().getAbsolutePath(), e.getMessage());
                }
            }
            else {
                log(Level.INFO, "log.record_charset", this.charset.name());
            }

            getByteBuffer().get(this.reservedFiller2);

            while(getByteBuffer().position() < this.firstRecordPosition - 1) {
                DBase3FieldDescriptor fd = new DBase3FieldDescriptor(getByteBuffer());
                this.fieldsDescriptors.add(fd);
                // loop until you hit the 0Dh field terminator
            }

            this.descriptorTerminator = getByteBuffer().get();

            // If the last character read after the field descriptor isn't 0x0D, the expected mark has not been found and the DBF is corrupted.
            if (this.descriptorTerminator != 0x0D) {
                String message = format(Level.WARNING, "excp.filedescriptor_problem", getFile().getAbsolutePath(), "Character marking the end of the fields descriptors (0x0D) has not been found.");
                throw new SQLInvalidDbaseFileFormatException(message);
            }
        }
        catch(BufferUnderflowException e) {
            // This exception doesn't denote a trouble of file opening because the file has been checked before
            // the calling of this private function.
            // Therefore, an internal structure problem cause maybe a premature End of file or anything else, but the only thing
            // we can conclude is : we are not before a device trouble, but a file format trouble.
            String message = format(Level.WARNING, "excp.filedescriptor_problem", getFile().getAbsolutePath(), e.getMessage());
            throw new SQLInvalidDbaseFileFormatException(message);
        }
    }

    /**
     * Returns the fields descriptors in their binary format.
     * @return Fields descriptors.
     */
    @Override
    public List<DBase3FieldDescriptor> getFieldsDescriptors() {
        return this.fieldsDescriptors;
    }

    /**
     * Return a field name.
     * @param columnIndex Column index.
     * @param sql For information, the SQL statement that is attempted.
     * @return Field Name.
     * @throws SQLIllegalColumnIndexException if the index is out of bounds.
     */
    @Override
    public String getFieldName(int columnIndex, String sql) throws SQLIllegalColumnIndexException {
        return getField(columnIndex, sql).getName();
    }

    /**
     * @see org.apache.sis.internal.shapefile.jdbc.Dbase3ByteReader#getColumnCount()
     */
    @Override
    public int getColumnCount() {
        return this.fieldsDescriptors.size();
    }

    /**
     * Returns the column index for the given column name.
     * The default implementation of all methods expecting a column label will invoke this method.
     * @param columnLabel The name of the column.
     * @param sql For information, the SQL statement that is attempted.
     * @return The index of the given column name : first column is 1.
     * @throws SQLNoSuchFieldException if there is no field with this name in the query.
     */
    @Override
    public int findColumn(String columnLabel, String sql) throws SQLNoSuchFieldException {
        // If the column name is null, no search is needed.
        if (columnLabel == null) {
            String message = format(Level.WARNING, "excp.no_such_column_in_resultset", columnLabel, sql, getFile().getName());
            throw new SQLNoSuchFieldException(message, sql, getFile(), columnLabel);
        }

        // Search the field among the fields descriptors.
        for(int index=0; index < this.fieldsDescriptors.size(); index ++) {
            if (this.fieldsDescriptors.get(index).getName().equals(columnLabel)) {
                return index + 1;
            }
        }

        // If we are here, we haven't found our field. Throw an exception.
        String message = format(Level.WARNING, "excp.no_such_column_in_resultset", columnLabel, sql, getFile().getName());
        throw new SQLNoSuchFieldException(message, sql, getFile(), columnLabel);
    }

    /**
     * Returns the field descriptor of a given ResultSet column index.
     * @param columnIndex Column index, first column is 1, second is 2, etc.
     * @param sql For information, the SQL statement that is attempted.
     * @return Field Descriptor.
     * @throws SQLIllegalColumnIndexException if the index is out of bounds.
     */
    private DBase3FieldDescriptor getField(int columnIndex, String sql) throws SQLIllegalColumnIndexException {
        if (columnIndex < 1 || columnIndex > getColumnCount()) {
            String message = format(Level.WARNING, "excp.illegal_column_index", columnIndex, getColumnCount());
            throw new SQLIllegalColumnIndexException(message, sql, getFile(), columnIndex);
        }

        return this.fieldsDescriptors.get(columnIndex-1);
    }
}
