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

import java.util.Map;
import java.util.LinkedHashMap;
import java.io.IOException;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.geom.AffineTransform;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.coverage.grid.GridCoverage;
import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.storage.StorageConnector;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.DataStoreReferencingException;
import org.apache.sis.storage.WritableGridCoverageResource;
import org.apache.sis.storage.IncompatibleResourceException;
import org.apache.sis.storage.base.WritableGridCoverageSupport;
import org.apache.sis.io.stream.ChannelDataOutput;
import org.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.image.PixelIterator;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.StringBuilders;

// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.coverage.grid.SequenceType;


/**
 * An ASCII Grid store with writing capabilities.
 *
 * @author  Martin Desruisseaux (Geomatys)
 */
final class WritableStore extends AsciiGridStore implements WritableGridCoverageResource {
    /**
     * The line separator for writing the ASCII file.
     */
    private final String lineSeparator;

    /**
     * The output if this store is write-only, or {@code null} if this store is read/write.
     * This is set to {@code null} when the store is closed.
     */
    private ChannelDataOutput output;

    /**
     * Creates a new ASCII Grid store from the given file, URL or stream.
     *
     * @param  provider   the factory that created this {@code DataStore} instance, or {@code null} if unspecified.
     * @param  connector  information about the storage (URL, stream, <i>etc</i>).
     * @throws DataStoreException if an error occurred while opening the stream.
     */
    public WritableStore(final AsciiGridStoreProvider provider, final StorageConnector connector) throws DataStoreException {
        super(provider, connector, false);
        lineSeparator = System.lineSeparator();
        if (!super.canReadOrWrite(false)) {
            output = connector.commit(ChannelDataOutput.class, AsciiGridStoreProvider.NAME);
        }
    }

    /**
     * Returns whether this store can read or write.
     */
    @Override
    boolean canReadOrWrite(final boolean write) {
        return write || super.canReadOrWrite(write);
    }

    /**
     * Returns an estimation of how close the "CRS to grid" transform is to integer values.
     * This is used for choosing whether to map pixel centers or pixel centers.
     */
    private static double distanceFromIntegers(final MathTransform gridToCRS) throws TransformException {
        final Matrix m = MathTransforms.getMatrix(gridToCRS.inverse());
        if (m != null && Matrices.isAffine(m)) {
            final int last = m.getNumCol() - 1;
            double sum = 0;
            for (int j=0; j<last; j++) {
                final double e = m.getElement(j, last);
                sum += Math.abs(Math.rint(e) - e);
            }
            return sum;
        }
        return Double.NaN;
    }

    /**
     * Gets the coefficients of the affine transform.
     *
     * @param  header  the map where to put the affine transform coefficients.
     * @param  gg      the grid geometry from which to get the affine transform.
     * @param  h       set of helper methods.
     * @return the iteration order (e.g. from left to right, then top to bottom).
     * @throws DataStoreException if the header cannot be written.
     */
    private static SequenceType getAffineCoefficients(
            final Map<String,Object> header, final GridGeometry gg,
            final WritableGridCoverageSupport h) throws DataStoreException
    {
        String xll = XLLCORNER;
        String yll = YLLCORNER;
        MathTransform gridToCRS = gg.getGridToCRS(PixelInCell.CELL_CORNER);
        try {
            final MathTransform alternative = gg.getGridToCRS(PixelInCell.CELL_CENTER);
            if (distanceFromIntegers(alternative) < distanceFromIntegers(gridToCRS)) {
                gridToCRS = alternative;
                xll = XLLCENTER;
                yll = YLLCENTER;
            }
        } catch (TransformException e) {
            throw new DataStoreReferencingException(h.canNotWrite(), e);
        }
        final AffineTransform at = h.getAffineTransform2D(gg.getExtent(), gridToCRS);
        if (at.getShearX() != 0 || at.getShearY() != 0) {
            throw new IncompatibleResourceException(h.rotationNotSupported(AsciiGridStoreProvider.NAME));
        }
        double scaleX =  at.getScaleX();
        double scaleY = -at.getScaleY();
        double x = at.getTranslateX();
        double y = at.getTranslateY();
        if (scaleX > 0 && scaleY > 0) {
            y -= scaleY * (Integer) header.get(NROWS);
        } else {
            /*
             * TODO: future version could support other signs, provided that
             * we implement `PixelIterator` for other `SequenceType` values.
             */
            throw new IncompatibleResourceException(h.canNotWrite());
        }
        header.put(xll, x);
        header.put(yll, y);
        if (scaleX == scaleY) {
            header.put(CELLSIZE, scaleX);
        } else {
            header.put(CELLSIZES[0], scaleX);
            header.put(CELLSIZES[1], scaleY);
        }
        return SequenceType.LINEAR;
    }

    /**
     * Writes the content of the given map as the header of ASCII Grid file.
     */
    private void writeHeader(final Map<String,Object> header, final ChannelDataOutput out) throws IOException {
        int maxKeyLength = 0;
        int maxValLength = 0;
        for (final Map.Entry<String,Object> entry : header.entrySet()) {
            final String text = entry.getValue().toString();
            entry.setValue(text);
            maxValLength = Math.max(maxValLength, text.length());
            maxKeyLength = Math.max(maxKeyLength, entry.getKey().length());
        }
        for (final Map.Entry<String,Object> entry : header.entrySet()) {
            String text = entry.getKey();
            write(text, out);
            write(CharSequences.spaces(maxKeyLength - text.length() + 1), out);
            text = (String) entry.getValue();
            write(CharSequences.spaces(maxValLength - text.length()), out);
            write(text, out);
            write(lineSeparator, out);
        }
    }

    /**
     * Writes a new coverage in the data store for this resource. If a coverage already exists for this resource,
     * then it will be overwritten only if the {@code TRUNCATE} or {@code UPDATE} option is specified.
     *
     * @param  coverage  new data to write in the data store for this resource.
     * @param  options   configuration of the write operation.
     * @throws DataStoreException if an error occurred while writing data in the underlying data store.
     */
    @Override
    public synchronized void write(GridCoverage coverage, final Option... options) throws DataStoreException {
        final var h = new WritableGridCoverageSupport(this, options);       // Does argument validation.
        final int band = 0;                                 // May become configurable in a future version.
        try {
            /*
             * If `output` is non-null, we are in write-only mode and there is no previously existing image.
             * Otherwise an image may exist and the behavior will depend on which options were supplied.
             */
            if (output == null && !h.replace(input().input)) {
                coverage = h.update(coverage);
            }
            final RenderedImage data = coverage.render(null);               // Fail if not two-dimensional.
            final Map<String,Object> header = new LinkedHashMap<>();
            header.put(NCOLS, data.getWidth());
            header.put(NROWS, data.getHeight());
            final SequenceType order = getAffineCoefficients(header, coverage.getGridGeometry(), h);
            /*
             * Open the destination channel only after the coverage has been validated by above method calls.
             * After this point we should not have any validation errors. Write the nodata value even if it is
             * "NaN" because the default is -9999, and we need to overwrite that default if it cannot be used.
             */
            final ChannelDataOutput out = (output != null) ? output : h.channel(input().input);
            final Number nodataValue = setCoverage(coverage, data, band);
            header.put(NODATA_VALUE, nodataValue);
            writeHeader(header, out);
            /*
             * Writes all sample values.
             */
            final float  nodataAsFloat  = nodataValue.floatValue();
            final double nodataAsDouble = nodataValue.doubleValue();
            final StringBuilder buffer  = new StringBuilder();
            final PixelIterator it      = new PixelIterator.Builder().setIteratorOrder(order).create(data);
            final int dataType          = it.getDataType().toDataBufferType();
            final int width             = it.getDomain().width;
            int remaining = width;
            while (it.next()) {
                switch (dataType) {
                    case DataBuffer.TYPE_DOUBLE: {
                        double value = it.getSampleDouble(band);
                        if (Double.isNaN(value)) {
                            value = nodataAsDouble;
                        }
                        buffer.append(value);
                        StringBuilders.trimFractionalPart(buffer);
                        break;
                    }
                    case DataBuffer.TYPE_FLOAT: {
                        float value = it.getSampleFloat(band);
                        if (Float.isNaN(value)) {
                            value = nodataAsFloat;
                        }
                        buffer.append(value);
                        StringBuilders.trimFractionalPart(buffer);
                        break;
                    }
                    default: {
                        buffer.append(it.getSample(band));
                        break;
                    }
                }
                write(buffer, out);
                buffer.setLength(0);
                if (--remaining != 0) {
                    out.writeByte(' ');
                } else {
                    write(lineSeparator, out);
                    remaining = width;
                }
            }
            out.flush();
            writePRJ();
            /*
             * If the channel is write-only (e.g. if we are writing in an `OutputStream`),
             * we will not be able to write a second time.
             */
            if (output != null) {
                output = null;
                out.channel.close();
            }
        } catch (IOException e) {
            closeOnError(e);
            throw new DataStoreException(e);
        }
    }

    /**
     * Writes the given text to the output. All characters must be US-ASCII (this is not verified).
     */
    private static void write(final CharSequence text, final ChannelDataOutput out) throws IOException {
        final int length = text.length();
        out.ensureBufferAccepts(length);
        for (int i=0; i<length; i++) {
            out.buffer.put((byte) text.charAt(i));
        }
    }

    /**
     * Closes this data store and releases any underlying resources.
     * If a read or write operation is in progress in another thread,
     * then this method blocks until that operation completed.
     * This restriction is for avoiding data lost.
     *
     * @throws DataStoreException if an error occurred while closing this data store.
     */
    @Override
    public synchronized void close() throws DataStoreException {
        listeners.close();                      // Should never fail.
        final ChannelDataOutput out = output;
        output = null;
        if (out != null) try {
            out.channel.close();
        } catch (IOException e) {
            throw new DataStoreException(e);
        }
        /*
         * No need for try-with-resource because only one
         * of `input` and `output` should be non-null.
         */
        super.close();
    }
}
