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

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Locale;
import java.io.File;
import java.nio.file.Path;
import java.text.ParseException;
import org.opengis.util.InternationalString;
import org.apache.sis.util.Static;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.ArgumentChecks;


/**
 * Static methods working on {@link TreeTable} objects and their nodes.
 * This class provides methods for some tasks considered generic enough,
 * and example codes for more specialized tasks that developers can customize.
 *
 * <p>The remaining of this class javadoc contains example codes placed in public domain.
 * Developers can copy and adapt those examples as they see fit.</p>
 *
 * <h2>Example 1: Reduce the depth of a tree</h2>
 * For every branch containing exactly one child, the following method concatenates in-place
 * that branch and its child together. This method can be used for simplifying depth trees into
 * something less verbose. For example given the tree on the left side, this method transforms
 * it into the tree on the right side:
 *
 * <table class="sis">
 * <caption>Example of tree depth reduction</caption>
 * <tr><th>Before</th><th class="sep">After</th></tr>
 * <tr><td>
 * {@preformat text
 *   root
 *     ├─users
 *     │   └─alice
 *     │       ├─data
 *     │       │   └─mercator
 *     │       └─document
 *     └─lib
 * }
 * </td><td class="sep">
 * {@preformat text
 *   root
 *     ├─users/alice
 *     │   ├─data/mercator
 *     │   └─document
 *     └─lib
 * }
 * </td></tr></table>
 * There is no pre-defined method for this task because there is too many parameters that
 * developers may want to customize (columns to merge, conditions for accepting the merge,
 * kind of objects to merge, name separator, <i>etc.</i>). In the following code snippet,
 * the content of the {@code NAME} columns are concatenated only if the {@code VALUE} column
 * has no value (for avoiding data lost when the node is discarded) and use the system file
 * separator as name separator:
 *
 * {@preformat java
 *     final TableColumn columnToProtect = TableColumn.VALUE;
 *     final TableColumn columnToConcatenate = TableColumn.NAME;
 *
 *     TreeTable.Node concatenateSingletons(final TreeTable.Node node) {
 *         // This simple example is restricted to nodes which are known to handle
 *         // their children in a list instead than some other kind of collection.
 *         final List<TreeTable.Node> children = (List<TreeTable.Node>) node.getChildren();
 *         final int size = children.size();
 *         for (int i=0; i<size; i++) {
 *             children.set(i, concatenateSingletons(children.get(i)));
 *         }
 *         if (size == 1) {
 *             final TreeTable.Node child = children.get(0);
 *             if (node.getValue(columnToProtect) == null) {
 *                 children.remove(0);
 *                 child.setValue(columnToConcatenate,
 *                         node .getValue(columnToConcatenate) + File.separator +
 *                         child.getValue(columnToConcatenate));
 *                 return child;
 *             }
 *         }
 *         return node;
 *     }
 * }
 *
 * @author  Martin Desruisseaux
 * @version 0.3
 *
 * @see TreeTable
 *
 * @since 0.3
 * @module
 */
public final class TreeTables extends Static {
    /**
     * Do not allow instantiation of this class.
     */
    private TreeTables() {
    }

    /**
     * Finds the node for the given path, or creates a new node if none exists.
     * First, this method searches in the node {@linkplain TreeTable.Node#getChildren()
     * children collection} for the root element of the given path. If no such node is found,
     * a {@linkplain TreeTable.Node#newChild() new child} is created. Then this method
     * repeats the process (searching in the children of the child for the second path
     * element), until the last path element is reached.
     *
     * <p>For example if the given path is {@code "users/alice/data"}, then this method
     * finds or creates the nodes for the following tree, where {@code "from"} is the
     * node given in argument to this method:</p>
     *
     * {@preformat text
     *   from
     *     └─users
     *         └─alice
     *             └─data
     * }
     *
     * @param  from    the root node from which to start the search.
     * @param  column  the column containing the file name.
     * @param  path    the path for which to find or create a node.
     * @return the node for the given path, either as an existing node or a new node.
     */
    public static TreeTable.Node nodeForPath(TreeTable.Node from,
            final TableColumn<? super String> column, final Path path)
    {
        final Path parent = path.getParent();
        if (parent != null) {
            from = nodeForPath(from, column, parent);
        }
        Path filename = path.getFileName();
        if (filename == null) {
            filename = path.getRoot();
        }
        final String name = filename.toString();
        for (final TreeTable.Node child : from.getChildren()) {
            if (name.equals(child.getValue(column))) {
                return child;
            }
        }
        from = from.newChild();
        from.setValue(column, name);
        return from;
    }

    /**
     * Finds the node for the given file, or creates a new node if none exists.
     * This method performs the same work than the above variant, but working on
     * {@code File} instances rather than {@code Path}.
     *
     * @param  from    the root node from which to start the search.
     * @param  column  the column containing the file name.
     * @param  path    the file for which to find or create a node.
     * @return the node for the given file, either as an existing node or a new node.
     */
    public static TreeTable.Node nodeForPath(TreeTable.Node from,
            final TableColumn<? super String> column, final File path)
    {
        final File parent = path.getParentFile();
        if (parent != null) {
            from = nodeForPath(from, column, parent);
        }
        String name = path.getName();
        if (name.isEmpty() && parent == null) {
            name = File.separator;                                  // Root directory in Unix path syntax.
        }
        for (final TreeTable.Node child : from.getChildren()) {
            if (name.equals(child.getValue(column))) {
                return child;
            }
        }
        from = from.newChild();
        from.setValue(column, name);
        return from;
    }

    /**
     * For every columns having values of type {@link CharSequence} or {@link String},
     * converts the values to localized {@code String}s. During conversions, this method also
     * replaces duplicated {@code String} instances by references to the same singleton instance.
     *
     * <p>This method may be invoked before to serialize the table in order to reduce the
     * serialization stream size.</p>
     *
     * @param  table   the table in which to replace values by their string representations.
     * @param  locale  the locale to use when replacing {@link InternationalString} instances. Can be {@code null}.
     * @return number of replacements done.
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static int replaceCharSequences(final TreeTable table, final Locale locale) {
        ArgumentChecks.ensureNonNull("table", table);
        final List<TableColumn<?>> columns = table.getColumns();
        TableColumn<? super String>[] filtered = new TableColumn[columns.size()];
        int count = 0;
        for (final TableColumn<?> column : columns) {
            if (column.getElementType().isAssignableFrom(String.class)) {
                filtered[count++] = (TableColumn<? super String>) column;
            }
        }
        filtered = ArraysExt.resize(filtered, count);
        return replaceCharSequences(table.getRoot(), filtered, locale, new HashMap<>());
    }

    /**
     * Implementation of the public {@link #replaceCharSequences(TreeTable, Locale)} method.
     *
     * @param  node     the node in which to replace values by their string representations.
     * @param  columns  the columns where to perform the replacements.
     * @param  locale   the locale to use when replacing {@link InternationalString} instances. Can be {@code null}.
     * @param  pool     an initially empty pool of string representations, to be filled by this method.
     * @return number of replacements done.
     */
    private static int replaceCharSequences(final TreeTable.Node node, final TableColumn<? super String>[] columns,
            final Locale locale, final Map<String,String> pool)
    {
        int changes = 0;
        for (final TreeTable.Node child : node.getChildren()) {
            changes += replaceCharSequences(child, columns, locale, pool);
        }
        for (final TableColumn<? super String> column : columns) {
            final Object value = node.getValue(column);
            if (value != null) {
                String text;
                if (value instanceof InternationalString) {
                    text = ((InternationalString) value).toString(locale);
                } else {
                    text = value.toString();
                }
                final String old = pool.put(text, text);
                if (old != null) {
                    pool.put(old, old);
                    text = old;
                }
                if (text != value) {
                    node.setValue(column, text);
                    changes++;
                }
            }
        }
        return changes;
    }

    /**
     * Returns a string representation of the given tree table.
     * The current implementation uses a shared instance of {@link TreeTableFormat}.
     * This is okay for debugging or occasional usages. However for more extensive usages,
     * developers are encouraged to create and configure their own {@code TreeTableFormat}
     * instance.
     *
     * @param  table  the tree table to format.
     * @return a string representation of the given tree table.
     */
    public static String toString(final TreeTable table) {
        ArgumentChecks.ensureNonNull("table", table);
        synchronized (TreeTableFormat.INSTANCE) {
            return TreeTableFormat.INSTANCE.format(table);
        }
    }

    /**
     * Parses the given string as tree.
     * This helper method is sometime useful for quick tests or debugging purposes.
     * For more extensive use, consider using {@link TreeTableFormat} instead.
     *
     * @param  tree          the string representation of the tree to parse.
     * @param  labelColumn   the columns where to store the node labels. This is often {@link TableColumn#NAME}.
     * @param  otherColumns  optional columns where to store the values, if any.
     * @return a tree parsed from the given string.
     * @throws ParseException if an error occurred while parsing the tree.
     */
    public static TreeTable parse(final String tree, final TableColumn<?> labelColumn,
            final TableColumn<?>... otherColumns) throws ParseException
    {
        ArgumentChecks.ensureNonNull("tree", tree);
        ArgumentChecks.ensureNonNull("labelColumn", labelColumn);
        TableColumn<?>[] columns = null; // Default to singleton(NAME).
        if (otherColumns.length != 0 || labelColumn != TableColumn.NAME) {
            columns = ArraysExt.insert(otherColumns, 0, 1);
            columns[0] = labelColumn;
        }
        final TreeTableFormat format = TreeTableFormat.INSTANCE;
        synchronized (format) {
            try {
                format.setColumns(columns);
                return format.parseObject(tree);
            } finally {
                format.setColumns((TableColumn<?>[]) null);
            }
        }
    }
}
