/*
 * 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.freemarker.generator.base.datasource;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator;
import org.apache.freemarker.generator.base.activation.ByteArrayDataSource;
import org.apache.freemarker.generator.base.activation.StringDataSource;
import org.apache.freemarker.generator.base.mime.MimeTypeParser;
import org.apache.freemarker.generator.base.util.CloseableReaper;
import org.apache.freemarker.generator.base.util.StringUtils;
import org.apache.freemarker.generator.base.util.Validate;

import javax.activation.FileDataSource;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
import static org.apache.freemarker.generator.base.FreeMarkerConstants.DATASOURCE_UNKNOWN_LENGTH;
import static org.apache.freemarker.generator.base.mime.Mimetypes.MIME_APPLICATION_OCTET_STREAM;

/**
 * Data source which encapsulates data to be used for rendering
 * a template. When accessing content it is loaded on demand and not
 * kept in memory to allow processing of large volumes of data.
 * <br>
 * There is also special support of <code>UrlDataSource</code> since
 * the content type &amp; charset might be determined using a network
 * call.
 * <br>
 * The implementation makes no assumption if the underlying input
 * stream can be consumed more than once.
 */
public class DataSource implements Closeable, javax.activation.DataSource {

    public static final String METADATA_BASE_NAME = "basename";
    public static final String METADATA_EXTENSION = "extension";
    public static final String METADATA_FILE_NAME = "filename";
    public static final String METADATA_FILE_PATH = "filepath";
    public static final String METADATA_GROUP = "group";
    public static final String METADATA_NAME = "name";
    public static final String METADATA_URI = "uri";
    public static final String METADATA_MIME_TYPE = "mimetype";

    public static final List<String> METADATA_KEYS = Arrays.asList(
            METADATA_BASE_NAME,
            METADATA_EXTENSION,
            METADATA_FILE_NAME,
            METADATA_FILE_PATH,
            METADATA_GROUP,
            METADATA_NAME,
            METADATA_URI,
            METADATA_MIME_TYPE
    );

    /** Human-readable name of the data source */
    private final String name;

    /** Optional group of data source */
    private final String group;

    /** The URI for loading the content of the data source */
    private final URI uri;

    /** The underlying "javax.activation.DataSource" */
    private final javax.activation.DataSource dataSource;

    /** Content type of data source either provided by the caller or fetched directly from the data source */
    private final String contentType;

    /** Charset for directly accessing text-based content */
    private final Charset charset;

    /** Additional properties as name/value pairs */
    private final Map<String, String> properties;

    /** Collect all closeables handed out to the caller to be closed when the data source is closed itself */
    private final CloseableReaper closeables;

    /**
     * Constructor.
     *
     * @param name        Human-readable name of the data source
     * @param group       Optional group of data source
     * @param uri         source URI of the data source
     * @param dataSource  JAF data source being wrapped
     * @param contentType content type of data source either provided by the caller or fetched directly from the data source
     * @param charset     option charset for directly accessing text-based content
     * @param properties  optional name/value pairs
     */
    public DataSource(
            String name,
            String group,
            URI uri,
            javax.activation.DataSource dataSource,
            String contentType,
            Charset charset,
            Map<String, String> properties) {
        this.name = requireNonNull(name).trim();
        this.group = StringUtils.emptyToNull(group);
        this.uri = requireNonNull(uri);
        this.dataSource = requireNonNull(dataSource);
        this.contentType = contentType;
        this.charset = charset;
        this.properties = properties != null ? new HashMap<>(properties) : new HashMap<>();
        this.closeables = new CloseableReaper();
    }

    @Override
    public String getName() {
        return name;
    }

    /**
     * Get the content type.
     *
     * @return content type
     */
    @Override
    public String getContentType() {
        return contentType();
    }

    /**
     * Get an input stream which is closed together with this data source.
     *
     * @return InputStream
     */
    @Override
    public InputStream getInputStream() {
        return closeables.add(getUnsafeInputStream());
    }

    @Override
    public OutputStream getOutputStream() {
        throw new RuntimeException("No output stream supported");
    }

    @Override
    public void close() {
        closeables.close();
    }

    public String getGroup() {
        return group;
    }

    /**
     * Get the file name from the underlying "FileDataSource". All
     * other data sources will return an empty string.
     *
     * @return file name or empty string
     */
    public String getFileName() {
        return isFileDataSource() ? FilenameUtils.getName(dataSource.getName()) : "";
    }

    /**
     * Get the base name from the underlying "FileDataSource". All
     * other data sources will return an empty string.
     *
     * @return base name or empty string
     */
    public String getBaseName() {
        return FilenameUtils.getBaseName(getFileName());
    }

    /**
     * Get the extension from the underlying "FileDataSource". All
     * other data sources will return an empty string.
     *
     * @return base name or empty string
     */
    public String getExtension() {
        return FilenameUtils.getExtension(getFileName());
    }

    /**
     * Get the charset. If no charset can be detected UTF-8 is assumed.
     *
     * @return charset
     */
    public Charset getCharset() {
        return charset != null ? charset : MimeTypeParser.getCharset(contentType(), UTF_8);
    }

    /**
     * Get the mime type , i.e. content type without additional charset parameter.
     *
     * @return mime type
     */
    public String getMimeType() {
        return MimeTypeParser.getMimeType(contentType());
    }

    public URI getUri() {
        return uri;
    }

    public Map<String, String> getProperties() {
        return properties;
    }

    /**
     * Try to get the length lazily, efficient and without consuming the input stream.
     *
     * @return Length of data source or UNKNOWN_LENGTH
     */
    public long getLength() {
        if (isFileDataSource()) {
            return ((FileDataSource) dataSource).getFile().length();
        } else if (isStringDataSource()) {
            return ((StringDataSource) dataSource).length();
        } else if (isByteArrayDataSource()) {
            return ((ByteArrayDataSource) dataSource).length();
        } else {
            return DATASOURCE_UNKNOWN_LENGTH;
        }
    }

    /**
     * Get an input stream which needs to be closed by the caller.
     *
     * @return InputStream
     */
    public InputStream getUnsafeInputStream() {
        try {
            return dataSource.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException("Failed to get input stream: " + this, e);
        }
    }

    public String getText() {
        return getText(getCharset().name());
    }

    public String getText(String charsetName) {
        Validate.notEmpty(charsetName, "No charset name provided");
        final StringWriter writer = new StringWriter();
        try (InputStream is = getUnsafeInputStream()) {
            IOUtils.copy(is, writer, Charset.forName(charsetName));
            return writer.toString();
        } catch (IOException e) {
            throw new RuntimeException("Failed to get text: " + this, e);
        }
    }

    /**
     * Get the content of an <code>InputStream</code> as a list of Strings,
     * one entry per line, using the specified character encoding.
     *
     * @return the list of Strings, never null
     */
    public List<String> getLines() {
        return getLines(getCharset().name());
    }

    /**
     * Gets the contents of an <code>InputStream</code> as a list of Strings,
     * one entry per line, using the specified character encoding.
     *
     * @param charsetName The name of the requested charset
     * @return the list of Strings, never null
     */
    public List<String> getLines(String charsetName) {
        Validate.notEmpty(charsetName, "No charset name provided");
        try (InputStream inputStream = getUnsafeInputStream()) {
            return IOUtils.readLines(inputStream, charsetName);
        } catch (IOException e) {
            throw new RuntimeException("Failed to get lines: " + this, e);
        }
    }

    /**
     * Returns an iterator for the lines in an <code>InputStream</code>, using
     * the default character encoding specified. The exposed iterator is closed
     * by the <code>DataSource</code>.
     *
     * @return line iterator
     */
    public LineIterator getLineIterator() {
        return getLineIterator(getCharset().name());
    }

    /**
     * Returns an Iterator for the lines in an <code>InputStream</code>, using
     * the character encoding specified. The exposed iterator is closed
     * by the <code>DataSource</code>.
     *
     * @param charsetName The name of the requested charset
     * @return line iterator
     */
    public LineIterator getLineIterator(String charsetName) {
        Validate.notEmpty(charsetName, "No charset name provided");
        return closeables.add(IOUtils.lineIterator(getUnsafeInputStream(), Charset.forName(charsetName)));
    }

    public byte[] getBytes() {
        try (InputStream inputStream = getUnsafeInputStream()) {
            return IOUtils.toByteArray(inputStream);
        } catch (IOException e) {
            throw new RuntimeException("Failed to get bytes: " + this, e);
        }
    }

    /**
     * Expose various parts of the metadata as simple strings to cater for filtering in a script.
     *
     * @param key key part key
     * @return value
     */
    public String getMetadata(String key) {
        Validate.notEmpty(key, "No key provided");
        switch (key) {
            case METADATA_BASE_NAME:
                return getBaseName();
            case METADATA_EXTENSION:
                return getExtension();
            case METADATA_FILE_NAME:
                return getFileName();
            case METADATA_FILE_PATH:
                return FilenameUtils.getFullPathNoEndSeparator(uri.getPath());
            case METADATA_GROUP:
                return getGroup();
            case METADATA_NAME:
                return getName();
            case METADATA_URI:
                return uri.toString();
            case METADATA_MIME_TYPE:
                return getMimeType();
            default:
                throw new IllegalArgumentException("Unknown metadata key: " + key);
        }
    }

    /**
     * Get all metadata parts as map.
     *
     * @return Map of metadata parts
     */
    public Map<String, String> getMetadata() {
        return METADATA_KEYS.stream()
                .collect(Collectors.toMap(key -> key, this::getMetadata));
    }

    /**
     * Matches a metadata key with a wildcard expression.
     *
     * @param key      metadata key, e.g. "name", "fileName", "baseName", "extension", "uri", "group"
     * @param wildcard the wildcard string to match against
     * @return true if the wildcard expression matches
     * @see <a href="https://commons.apache.org/proper/commons-io/javadocs/api-2.7/org/apache/commons/io/FilenameUtils.html#wildcardMatch-java.lang.String-java.lang.String-">Apache Commons IO</a>
     */
    public boolean match(String key, String wildcard) {
        final String value = getMetadata(key);
        return FilenameUtils.wildcardMatch(value, wildcard);
    }

    /**
     * Some tools create a {@link java.io.Closeable} which can bound to the
     * lifecycle of the data source. When the data source is closed all the
     * associated {@link java.io.Closeable} are closed as well.
     *
     * @param closeable Closable
     * @param <T>       Type of closable
     * @return Closable
     */
    public <T extends Closeable> T addClosable(T closeable) {
        return closeables.add(closeable);
    }

    @Override
    public String toString() {
        return "DataSource{" +
                "name='" + name + '\'' +
                ", group='" + group + '\'' +
                ", uri=" + uri +
                '}';
    }

    /**
     * If there is no content type we ask the underlying data source. E.g. for
     * an <code>URLDataSource</code> this information is fetched from the
     * remote server.
     *
     * @return content type
     */
    private String contentType() {
        if (StringUtils.isNotEmpty(contentType)) {
            return contentType;
        } else {
            final String contentType = dataSource.getContentType();
            return StringUtils.firstNonEmpty(contentType, MIME_APPLICATION_OCTET_STREAM);
        }
    }

    private boolean isFileDataSource() {
        return dataSource instanceof FileDataSource;
    }

    private boolean isStringDataSource() {
        return dataSource instanceof StringDataSource;
    }

    private boolean isByteArrayDataSource() {
        return dataSource instanceof ByteArrayDataSource;
    }
}
