/*
 * 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.sling.servlets.get.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceNotFoundException;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.servlets.get.impl.helpers.HeadServletResponse;
import org.apache.sling.servlets.get.impl.helpers.HtmlRendererServlet;
import org.apache.sling.servlets.get.impl.helpers.JsonRendererServlet;
import org.apache.sling.servlets.get.impl.helpers.PlainTextRendererServlet;
import org.apache.sling.servlets.get.impl.helpers.StreamRendererServlet;
import org.apache.sling.servlets.get.impl.helpers.XMLRendererServlet;
import org.apache.sling.xss.XSSAPI;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A SlingSafeMethodsServlet that renders the current Resource as simple HTML
 */
@Component(service = Servlet.class,
    name="org.apache.sling.servlets.get.DefaultGetServlet",
    property = {
            "service.description=Default GET Servlet",
            "service.vendor=The Apache Software Foundation",

            // Use this as a default servlet for Sling
            "sling.servlet.resourceTypes=sling/servlet/default",
            "sling.servlet.prefix:Integer=-1",

            // Generic handler for all get requests
            "sling.servlet.methods=GET",
            "sling.servlet.methods=HEAD"
    })
@Designate(ocd=DefaultGetServlet.Config.class)
public class DefaultGetServlet extends SlingSafeMethodsServlet {

    private static final long serialVersionUID = -2714152339750885354L;

    @ObjectClassDefinition(name="Apache Sling GET Servlet",
            description="The Sling GET servlet is registered as the default servlet to handle GET requests.")
    public @interface Config {

        @AttributeDefinition(name = "Extension Aliases",
                description="The aliases can be used to map several extensions to a " +
                            "single servlet. For instance \"xml:pdf,rtf\" maps the extensions \".pdf\" and " +
                            "\".rtf\" to the servlet helper handling the \".xml\" extension.")
        String[] aliases();

        @AttributeDefinition(name = "Auto Index",
                description="Controls whether a simple directory index is rendered for " +
                             "a directory request. A directory request is a request to a resource with a " +
                             "trailing slash (/) character, for example http://host/apps/. If none of the " +
                             "index resources exists, the default GET servlet may automatically render an " +
                             "index listing of the child resources if this option is checked, which is the " +
                             "default. If this option is not checked, the request to the resource is " +
                             "forbidden and results in a status 403/FORBIDDEN. This configuration " +
                             "corresponds to the \"Index\" option of the Options directive of Apache HTTP " +
                             "Server (httpd).")
        boolean index() default false;

        @AttributeDefinition(name = "Index Resources",
                description = "List of child resources to be considered for rendering  " +
                             "the index of a \"directory\". The default value is [ \"index\", \"index.html\" ].  " +
                             "Each entry in the list is checked and the first entry found is included to  " +
                             "render the index. If an entry is selected, which has not extension (for  " +
                             "example the \"index\" resource), the extension \".html\" is appended for the  " +
                             "inclusion to indicate the desired text/html rendering. If the resource name  " +
                             "has an extension (as in \"index.html\"), no additional extension is appended  " +
                             "for the inclusion. This configuration corresponds to the <DirectoryIndex>  " +
                             "directive of Apache HTTP Server (httpd).")
        String[] index_files() default { "index","index.html" };

        @AttributeDefinition(name = "Enable HTML",
                description = "Whether the renderer for HTML of the default GET servlet is enabled or not. By default the HTML renderer is enabled.")
        boolean enable_html() default true;

        @AttributeDefinition(name = "Enable JSON",
                description = "Whether the renderer for JSON of the default GET servlet is enabled or not. By default the JSON renderer is enabled.")
        boolean enable_json() default true;

        @AttributeDefinition(name = "Enable Plain Text",
                description = "Whether the renderer for plain text of the default GET servlet is enabled or not. By default the plain text renderer is enabled.")
        boolean enable_txt() default true;

        @AttributeDefinition(name = "Enable XML",
                description = "Whether the renderer for XML of the default GET servlet is enabled or not. By default the XML renderer is enabled.")
        boolean enable_xml() default true;

        @AttributeDefinition(name = "JSON Max results",
                description = "The maximum number of resources that should " +
                  "be returned when doing a node.5.json or node.infinity.json. In JSON terms " +
                  "this basically means the number of Objects to return. Default value is " +
                  "200.")
        int json_maximumresults() default 200;
    }

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private Map<String, Servlet> rendererMap = new HashMap<>();

    private int jsonMaximumResults;

    /** Additional aliases. */
    private String[] aliases;

    /** Whether to support automatic index rendering */
    private boolean index;

    /** The names of index rendering children */
    private String[] indexFiles;

    private boolean enableHtml;

    private boolean enableTxt;

    private boolean enableJson;

    private boolean enableXml;

    @Reference(policyOption = ReferencePolicyOption.GREEDY)
    private XSSAPI xssApi;
    
    public static final String EXT_HTML = "html";

    public static final String EXT_TXT = "txt";

    public static final String EXT_JSON = "json";

    public static final String EXT_XML = "xml";

    public static final String EXT_RES = "res";

    @Activate
    protected void activate(Config cfg) {
        this.aliases = cfg.aliases();
        this.index = cfg.index();
        this.indexFiles = cfg.index_files();
        if ( this.indexFiles == null ) {
            this.indexFiles = new String[0];
        }

        this.enableHtml = cfg.enable_html();
        this.enableTxt = cfg.enable_txt();
        this.enableJson = cfg.enable_json();
        this.enableXml = cfg.enable_xml();
        this.jsonMaximumResults = cfg.json_maximumresults();
    }

    @Deactivate
    protected void deactivate() {
        this.aliases = null;
        this.index = false;
        this.indexFiles = null;
    }

    private Servlet getDefaultRendererServlet(final String type) {
        Servlet servlet = null;
        if ( EXT_RES.equals(type) ) {
            servlet = new StreamRendererServlet(index, indexFiles);
        } else if ( EXT_HTML.equals(type) ) {
            servlet = new HtmlRendererServlet(xssApi);
        } else if ( EXT_TXT.equals(type) ) {
            servlet = new PlainTextRendererServlet();
        } else if (EXT_JSON.equals(type) ) {
            servlet = new JsonRendererServlet(jsonMaximumResults);
        } else if ( EXT_XML.equals(type) ) {
            try {
                servlet = new XMLRendererServlet();
            } catch (Throwable t) {
                logger.warn("Support for getting XML is currently disabled " +
                        "in the servlets get module. Check whether the JCR API is available.");
            }
        }
        if ( servlet != null ) {
            try {
                servlet.init(getServletConfig());
            } catch (Throwable t) {
                logger.error("Error while initializing servlet " + servlet, t);
                servlet = null;
            }
        }
        return servlet;
    }

    @Override
    public void init() throws ServletException {
        super.init();

        // use the servlet for rendering StreamRendererServlet.EXT_RES as the
        // streamer servlet
        Servlet streamerServlet = getDefaultRendererServlet(EXT_RES);

        rendererMap.put(null, streamerServlet);
        
        rendererMap.put(EXT_RES, streamerServlet);
        
        if (enableHtml) {
            rendererMap.put(EXT_HTML,
                    getDefaultRendererServlet(EXT_HTML));
        }

        if (enableTxt) {
            rendererMap.put(EXT_TXT,
                    getDefaultRendererServlet(EXT_TXT));
        }

        if (enableJson) {
            rendererMap.put(EXT_JSON,
                    getDefaultRendererServlet(EXT_JSON));
        }

        if (enableXml) {
            rendererMap.put(EXT_XML,
                    getDefaultRendererServlet(EXT_XML));
        }


        // check additional aliases
        if (this.aliases != null) {
            for (final String m : aliases) {
                final int pos = m.indexOf(':');
                if (pos != -1) {
                    final String type = m.substring(0, pos);
                    Servlet servlet = rendererMap.get(type);
                    if ( servlet == null ) {
                        servlet = getDefaultRendererServlet(type);
                    }
                    if (servlet != null) {
                        final String extensions = m.substring(pos + 1);
                        final StringTokenizer st = new StringTokenizer(
                            extensions, ",");
                        while (st.hasMoreTokens()) {
                            final String ext = st.nextToken();
                            rendererMap.put(ext, servlet);
                        }
                    } else {
                        logger.warn("Unable to enable renderer alias(es) for {} - type not supported", m);
                    }
                }
            }
        }
    }

    /**
     * @throws ResourceNotFoundException if the resource of the request is a non
     *             existing resource.
     */
    @Override
    protected void doGet(SlingHttpServletRequest request,
            SlingHttpServletResponse response) throws ServletException,
            IOException {

        // cannot handle the request for missing resources
        if (ResourceUtil.isNonExistingResource(request.getResource())) {
            throw new ResourceNotFoundException(
                request.getResource().getPath(), "No resource found");
        }

        Servlet rendererServlet;
        String ext = request.getRequestPathInfo().getExtension();
        rendererServlet = rendererMap.get(ext);

        // fail if we should not just stream or we cannot support the ext.
        if (rendererServlet == null) {
            request.getRequestProgressTracker().log(
                "No renderer for extension " + ext);
            // if this is an included request, sendError() would fail
            // as the response is already committed, in this case we just
            // do nothing (but log an error message)
            if (response.isCommitted()
                || request.getAttribute(SlingConstants.ATTR_REQUEST_SERVLET) != null) {
                logger.error(
                    "No renderer for extension {}, cannot render resource {}",
                    ext, request.getResource());
            } else {
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
            }
            return;
        }

        request.getRequestProgressTracker().log(
            "Using " + rendererServlet.getClass().getName()
                + " to render for extension=" + ext);
        rendererServlet.service(request, response);
    }

    @Override
    protected void doHead(SlingHttpServletRequest request,
                          SlingHttpServletResponse response) throws ServletException,
            IOException {

        response = new HeadServletResponse(response);
        doGet(request, response);
    }

    @Override
    public void destroy() {

        for (Servlet servlet : rendererMap.values()) {
            try {
                servlet.destroy();
            } catch (Throwable t) {
                logger.error("Error while destroying servlet " + servlet, t);
            }
        }

        rendererMap.clear();

        super.destroy();
    }
}
