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

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.ResponseUtil;
import org.apache.tomcat.util.http.parser.AcceptEncoding;
import org.apache.tomcat.util.http.parser.TE;
import org.apache.tomcat.util.http.parser.TokenList;
import org.apache.tomcat.util.res.StringManager;

/**
 * Configuration for HTTP response compression settings.
 */
public class CompressionConfig {

    /**
     * Creates a new compression configuration with default settings.
     */
    public CompressionConfig() {
    }

    private static final Log log = LogFactory.getLog(CompressionConfig.class);
    private static final StringManager sm = StringManager.getManager(CompressionConfig.class);

    private int compressionLevel = 0;
    private Pattern noCompressionUserAgents = null;
    private String compressibleMimeType = "text/html,text/xml,text/plain,text/css," +
            "text/javascript,application/javascript,application/json,application/xml";
    private String[] compressibleMimeTypes = null;
    private int compressionMinSize = 2048;
    private Set<String> noCompressionEncodings =
            new HashSet<>(Arrays.asList("br", "compress", "dcb", "dcz", "deflate", "gzip", "pack200-gzip", "zstd"));


    /**
     * Returns the list of content encodings that indicate already-compressed content.
     *
     * @return comma-separated list of encoding names
     */
    public String getNoCompressionEncodings() {
        return String.join(",", noCompressionEncodings);
    }


    /**
     * Set the list of content encodings that indicate already-compressed content.
     * When content is already encoded with one of these encodings, compression will not be applied
     * to prevent double compression.
     *
     * @param encodings Comma-separated list of encoding names (e.g., "gzip,br.dflate")
     */
    public void setNoCompressionEncodings(String encodings) {
        Set<String> newEncodings = new HashSet<>();
        if (encodings != null && !encodings.isEmpty()) {
            StringTokenizer tokens = new StringTokenizer(encodings, ",");
            while (tokens.hasMoreTokens()) {
                String token = tokens.nextToken().trim();
                if(!token.isEmpty()) {
                    newEncodings.add(token);
                }
            }
        }
        this.noCompressionEncodings = newEncodings;
    }


    /**
     * Set compression level.
     *
     * @param compression One of <code>on</code>, <code>force</code>, <code>off</code> or the minimum compression size
     *                        in bytes which implies <code>on</code>
     */
    public void setCompression(String compression) {
        switch (compression) {
            case "on" -> this.compressionLevel = 1;
            case "force" -> this.compressionLevel = 2;
            case "off" -> this.compressionLevel = 0;
            default -> {
                try {
                    // Try to parse compression as an int, which would give the
                    // minimum compression size
                    setCompressionMinSize(Integer.parseInt(compression));
                    this.compressionLevel = 1;
                } catch (Exception e) {
                    this.compressionLevel = 0;
                }
            }
        }
    }


    /**
     * Return compression level.
     *
     * @return The current compression level in string form (off/on/force)
     */
    public String getCompression() {
        return switch (compressionLevel) {
            case 1 -> "on";
            case 2 -> "force";
            default -> "off";
        };
    }


    /**
     * Returns the internal numeric compression level.
     *
     * @return 0 for off, 1 for on, 2 for force
     */
    public int getCompressionLevel() {
        return compressionLevel;
    }


    /**
     * Obtain the String form of the regular expression that defines the user agents to not use gzip with.
     *
     * @return The regular expression as a String
     */
    public String getNoCompressionUserAgents() {
        if (noCompressionUserAgents == null) {
            return null;
        } else {
            return noCompressionUserAgents.toString();
        }
    }


    /**
     * Returns the compiled regular expression pattern for user agents that should not
     * receive compressed responses.
     *
     * @return the compiled pattern, or {@code null} if not configured
     */
    public Pattern getNoCompressionUserAgentsPattern() {
        return noCompressionUserAgents;
    }


    /**
     * Set no compression user agent pattern. Regular expression as supported by {@link Pattern}.
     *
     * @param noCompressionUserAgents The regular expression for user agent strings for which compression should not be
     *                                    applied
     */
    public void setNoCompressionUserAgents(String noCompressionUserAgents) {
        if (noCompressionUserAgents == null || noCompressionUserAgents.isEmpty()) {
            this.noCompressionUserAgents = null;
        } else {
            this.noCompressionUserAgents = Pattern.compile(noCompressionUserAgents);
        }
    }


    /**
     * Returns the comma-separated list of MIME types eligible for compression.
     *
     * @return comma-separated MIME type string
     */
    public String getCompressibleMimeType() {
        return compressibleMimeType;
    }


    /**
     * Sets the comma-separated list of MIME types eligible for compression.
     *
     * @param valueS comma-separated MIME type string
     */
    public void setCompressibleMimeType(String valueS) {
        compressibleMimeType = valueS;
        compressibleMimeTypes = null;
    }


    /**
     * Returns the array of MIME types eligible for compression.
     *
     * @return array of MIME type strings
     */
    public String[] getCompressibleMimeTypes() {
        String[] result = compressibleMimeTypes;
        if (result != null) {
            return result;
        }
        List<String> values = new ArrayList<>();
        StringTokenizer tokens = new StringTokenizer(compressibleMimeType, ",");
        while (tokens.hasMoreTokens()) {
            String token = tokens.nextToken().trim();
            if (!token.isEmpty()) {
                values.add(token);
            }
        }
        result = values.toArray(new String[0]);
        compressibleMimeTypes = result;
        return result;
    }


    /**
     * Returns the minimum response size in bytes required before compression is applied.
     *
     * @return the minimum size in bytes
     */
    public int getCompressionMinSize() {
        return compressionMinSize;
    }


    /**
     * Set Minimum size to trigger compression.
     *
     * @param compressionMinSize The minimum content length required for compression in bytes
     */
    public void setCompressionMinSize(int compressionMinSize) {
        this.compressionMinSize = compressionMinSize;
    }


    /**
     * Determines if compression should be enabled for the given response and if it is, sets any necessary headers to
     * mark it as such.
     *
     * @param request  The request that triggered the response
     * @param response The response to consider compressing
     *
     * @return {@code true} if compression was enabled for the given response, otherwise {@code false}
     */
    public boolean useCompression(Request request, Response response) {
        // Check if compression is enabled
        if (compressionLevel == 0) {
            return false;
        }

        boolean useTransferEncoding = false;
        boolean useContentEncoding = true;

        MimeHeaders responseHeaders = response.getMimeHeaders();

        // Check if content is not already compressed
        MessageBytes contentEncodingMB = responseHeaders.getValue("Content-Encoding");
        if (contentEncodingMB != null) {
            // Content-Encoding values are ordered but order is not important
            // for this check so use a Set rather than a List
            Set<String> tokens = new HashSet<>();
            try {
                TokenList.parseTokenList(responseHeaders.values("Content-Encoding"), tokens);
            } catch (IOException ioe) {
                // Because we are using StringReader, any exception here is a
                // Tomcat bug.
                log.warn(sm.getString("compressionConfig.ContentEncodingParseFail"), ioe);
                return false;
            }
            if (tokens.contains("identity")) {
                // If identity, do not do content modifications
                useContentEncoding = false;
            } else if (noCompressionEncodings.stream().anyMatch(tokens::contains)) {
                // Content should not be compressed twice
                return false;
            }
        }

        // If force mode, the length and MIME type checks are skipped
        if (compressionLevel != 2) {
            // Check if the response is of sufficient length to trigger the compression
            long contentLength = response.getContentLengthLong();
            if (contentLength != -1 && contentLength < compressionMinSize) {
                return false;
            }

            // Check for compatible MIME-TYPE
            String[] compressibleMimeTypes = getCompressibleMimeTypes();
            if (compressibleMimeTypes != null &&
                    !startsWithStringArray(compressibleMimeTypes, response.getContentType())) {
                return false;
            }
        }

        Enumeration<String> headerValues = request.getMimeHeaders().values("TE");
        boolean foundGzip = false;
        // TE and accept-encoding seem to have equivalent syntax
        while (!foundGzip && headerValues.hasMoreElements()) {
            List<TE> tes;
            try {
                tes = TE.parse(new StringReader(headerValues.nextElement()));
            } catch (IOException ioe) {
                // If there is a problem reading the header, disable compression
                return false;
            }

            for (TE te : tes) {
                if ("gzip".equalsIgnoreCase(te.getEncoding())) {
                    useTransferEncoding = true;
                    foundGzip = true;
                    break;
                }
            }
        }

        // Check if the resource has a strong ETag
        String eTag = responseHeaders.getHeader("ETag");
        if (!useTransferEncoding && eTag != null && !eTag.trim().startsWith("W/")) {
            // Has an ETag that doesn't start with "W/..." so it must be a
            // strong ETag
            return false;
        }

        if (useContentEncoding && !useTransferEncoding) {
            // If processing reaches this far, the response might be compressed.
            // Therefore, set the Vary header to keep proxies happy
            ResponseUtil.addVaryFieldName(responseHeaders, "accept-encoding");

            // Check if user-agent supports gzip encoding
            // Only interested in whether gzip encoding is supported. Other
            // encodings and weights can be ignored.
            headerValues = request.getMimeHeaders().values("accept-encoding");
            while (!foundGzip && headerValues.hasMoreElements()) {
                List<AcceptEncoding> acceptEncodings;
                try {
                    acceptEncodings = AcceptEncoding.parse(new StringReader(headerValues.nextElement()));
                } catch (IOException ioe) {
                    // If there is a problem reading the header, disable compression
                    return false;
                }

                for (AcceptEncoding acceptEncoding : acceptEncodings) {
                    if ("gzip".equalsIgnoreCase(acceptEncoding.getEncoding())) {
                        foundGzip = true;
                        break;
                    }
                }
            }
        }

        if (!foundGzip) {
            return false;
        }

        // If force mode, the browser checks are skipped
        if (compressionLevel != 2) {
            // Check for incompatible Browser
            Pattern noCompressionUserAgents = this.noCompressionUserAgents;
            if (noCompressionUserAgents != null) {
                MessageBytes userAgentValueMB = request.getMimeHeaders().getValue("user-agent");
                if (userAgentValueMB != null) {
                    String userAgentValue = userAgentValueMB.toString();
                    if (noCompressionUserAgents.matcher(userAgentValue).matches()) {
                        return false;
                    }
                }
            }
        }

        // All checks have passed. Compression is enabled.

        // Compressed content length is unknown so mark it as such.
        response.setContentLength(-1);
        if (useTransferEncoding) {
            // Configure the transfer encoding for compressed content
            responseHeaders.addValue("Transfer-Encoding").setString("gzip");
        } else {
            // Configure the content encoding for compressed content
            responseHeaders.addValue("Content-Encoding").setString("gzip");
        }

        return true;
    }


    /**
     * Checks if any entry in the string array starts with the specified value
     *
     * @param sArray the StringArray
     * @param value  string
     */
    private static boolean startsWithStringArray(String[] sArray, String value) {
        if (value == null) {
            return false;
        }
        for (String s : sArray) {
            if (value.startsWith(s)) {
                return true;
            }
        }
        return false;
    }
}
