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

import java.util.Collection;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.concurrent.atomic.AtomicInteger;
import java.time.DateTimeException;
import java.io.IOException;
import org.apache.sis.util.ObjectConverter;
import org.apache.sis.util.ObjectConverters;
import org.apache.sis.util.collection.BackingStoreException;

// Branch-dependent imports
import org.apache.sis.feature.AbstractFeature;
import org.apache.sis.feature.AbstractIdentifiedType;
import org.apache.sis.feature.DefaultAttributeType;


/**
 * Base implementation of iterators returned by {@link Store#features(boolean)}. This base class returns one feature
 * per line. For example iteration over the following file will produce 4 {@code Feature} instances, even if there is
 * actually only three distinct instances because the feature "a" is splitted on 2 lines:
 *
 * {@preformat text
 *    a,  10, 150, 11.0 2.0 12.0 3.0
 *    b,  10, 190, 10.0 2.0 11.0 3.0
 *    a, 150, 190, 12.0 3.0 10.0 3.0
 *    c,  10, 190, 12.0 1.0 10.0 2.0 11.0 3.0
 * }
 *
 * <b>Multi-threading:</b> {@code Iter} is not thread-safe.
 * However many {@code Iter} instances can be used concurrently for the same {@link Store} instance.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.8
 * @since   0.7
 * @module
 */
class FeatureIterator implements Spliterator<AbstractFeature> {
    /**
     * Index of the column containing trajectory coordinates.
     * Columns before the trajectory are Moving Feature identifier {@code mfIdRef}, start time and end time.
     */
    static final int TRAJECTORY_COLUMN = 3;

    /**
     * Connection to the CSV file.
     */
    final Store store;

    /**
     * Name of the property where to store a value.
     * This array be considered unmodifiable and may be shared between many {@code Iter} instances.
     */
    final String[] propertyNames;

    /**
     * Converters from string representations to the values to store in the {@link #values} array.
     * This array be considered unmodifiable and may be shared between many {@code Iter} instances.
     */
    final ObjectConverter<String,?>[] converters;

    /**
     * All values found in a row. We need to remember those values between different executions
     * of the {@link #tryAdvance(Consumer)} method because the Moving Feature Specification said:
     * "If the value equals the previous value, the text for the value can be omitted."
     */
    final Object[] values;

    /**
     * Number of calls to {@link #trySplit()}. Created only if needed.
     */
    private AtomicInteger splitCount;

    /**
     * Creates a new iterator.
     */
    @SuppressWarnings({"unchecked", "rawtypes", "fallthrough"})
    FeatureIterator(final Store store) {
        this.store = store;
        final Collection<? extends AbstractIdentifiedType> properties = store.featureType.getProperties(true);
        converters    = new ObjectConverter[properties.size()];
        values        = new Object[converters.length];
        propertyNames = new String[converters.length];
        int i = -1;
        for (final AbstractIdentifiedType p : properties) {
            propertyNames[++i] = p.getName().tip().toString();
            /*
             * According Moving Features specification:
             *   Column 0 is the feature identifier (mfidref). There is nothing special to do here.
             *   Column 1 is the start time.
             *   Column 2 is the end time.
             *   Column 3 is the trajectory.
             *   Columns 4+ are custom attributes.
             */
            final ObjectConverter<String,?> c;
            switch (i) {
                case 1: // Fall through
                case 2: {
                    final TimeEncoding timeEncoding = store.timeEncoding();
                    if (timeEncoding != null) {
                        c = timeEncoding;
                        break;
                    }
                    /*
                     * If there is no time columns, then this column may be the trajectory (note that allowing
                     * CSV files without time is obviously a departure from Moving Features specification.
                     * The intent is to have a CSV format applicable to other features than moving ones).
                     * Fall through in order to process trajectory.
                     */
                }
                case TRAJECTORY_COLUMN: {
                    if (store.hasTrajectories()) {
                        c = GeometryParser.INSTANCE;
                        break;
                    }
                    /*
                     * If there is no trajectory columns, than this column is a custum attribute.
                     * CSV files without trajectories are not compliant with Moving Feature spec.,
                     * but we try to keep this reader a little bit more generic.
                     */
                }
                default: {
                    c = ObjectConverters.find(String.class, ((DefaultAttributeType) p).getValueClass());
                    break;
                }
            }
            converters[i] = c;
        }
    }

    /**
     * Creates a new iterator using the same configuration than the given iterator.
     * This constructor is for {@link #trySplit()} implementation only.
     */
    private FeatureIterator(final FeatureIterator other) {
        store         = other.store;
        splitCount    = other.splitCount;
        converters    = other.converters;
        propertyNames = other.propertyNames;
        values        = new Object[converters.length];
    }

    /**
     * If this spliterator can be partitioned, returns a {@code Spliterator} covering elements.
     * This method does not make any guarantees about iteration order; i.e. the returned iterator
     * is not guaranteed to cover a strict prefix of the elements.
     */
    @Override
    public Spliterator<AbstractFeature> trySplit() {
        if (splitCount == null) {
            splitCount = new AtomicInteger();
        }
        if (splitCount.incrementAndGet() < 8) {        // Arbitrary limit.
            return new FeatureIterator(this);
        }
        return null;
    }

    /**
     * Executes the given action only on the next feature, if any.
     */
    @Override
    public boolean tryAdvance(final Consumer<? super AbstractFeature> action) {
        try {
            return read(action, false);
        } catch (IOException | IllegalArgumentException | DateTimeException e) {
            throw new BackingStoreException(store.canNotParseFile(), e);
        }
    }

    /**
     * Executes the given action on all remaining features.
     */
    @Override
    public void forEachRemaining(final Consumer<? super AbstractFeature> action) {
        try {
            read(action, true);
        } catch (IOException | IllegalArgumentException | DateTimeException e) {
            throw new BackingStoreException(store.canNotParseFile(), e);
        }
    }

    /**
     * Executes the given action for the next feature or for all remaining features.
     * The features are assumed static, with one feature per line.
     * This method is for {@link #tryAdvance(Consumer)} and {@link #forEachRemaining(Consumer)} implementations.
     *
     * <p><b>Multi-threading:</b>
     * {@code Iter} does not need to be thread-safe, so we do not perform synchronization for its {@link #values}.
     * Accesses to {@code Store} fields need to be thread-safe, but this method uses only immutable or thread-safe
     * objects from {@link Store}, so there is no need for {@code synchronize(Store.this)} statement.
     * The only object that need synchronization is {@link Store#source}, which is already synchronized.</p>
     *
     * @param  action  the action to execute.
     * @param  all     {@code true} for executing the given action on all remaining features.
     * @return {@code false} if there is no remaining feature after this method call.
     * @throws IOException if an I/O error occurred while reading a feature.
     * @throws IllegalArgumentException if parsing of a number failed, or other error.
     * @throws DateTimeException if parsing of a date failed.
     */
    private boolean read(final Consumer<? super AbstractFeature> action, final boolean all) throws IOException {
        final FixedSizeList elements = new FixedSizeList(values);
        String line;
        while ((line = store.readLine()) != null) {
            Store.split(line, elements);
            final AbstractFeature feature = store.featureType.newInstance();
            int i, n = elements.size();
            for (i=0; i<n; i++) {
                values[i] = converters[i].apply((String) values[i]);
                feature.setPropertyValue(propertyNames[i], values[i]);
            }
            n = values.length;
            for (; i<n; i++) {
                // For omitted elements, reuse previous value.
                feature.setPropertyValue(propertyNames[i], values[i]);
            }
            action.accept(feature);
            if (!all) return true;
            elements.clear();
        }
        return false;
    }

    /**
     * We do not know the number of features.
     */
    @Override
    public long estimateSize() {
        return Long.MAX_VALUE;
    }

    /**
     * Returns the characteristics of the iteration over feature instances.
     * The iteration is {@link #NONNULL} (i.e. {@link #tryAdvance(Consumer)} is not allowed
     * to return null value) and {@link #IMMUTABLE} (i.e. we do not support modification of
     * the CSV file while an iteration is in progress).
     * The iteration is not declared {@link #ORDERED} because {@link #trySplit()} does not
     * return a strict prefix of the elements.
     *
     * @return characteristics of iteration over the features in the CSV file.
     */
    @Override
    public int characteristics() {
        return NONNULL | IMMUTABLE;
    }
}
