/*
 * 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.HtmlRenderer;
import org.apache.sling.servlets.get.impl.helpers.JsonRenderer;
import org.apache.sling.servlets.get.impl.helpers.PlainTextRenderer;
import org.apache.sling.servlets.get.impl.helpers.Renderer;
import org.apache.sling.servlets.get.impl.helpers.StreamRenderer;
import org.apache.sling.servlets.get.impl.helpers.XMLRenderer;
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;
        
        @AttributeDefinition(name = "ECMA date Support", description="Enable deprecated ECMA formatting for JSON response")
        boolean ecmaSuport() default false;
    }

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

    private Map<String, Renderer> 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;

	private boolean enableEcmaSupport;
    
    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();
        this.enableEcmaSupport = cfg.ecmaSuport();
    }

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

    private Renderer getDefaultRenderer(final String type) {
    	Renderer renderer = null;
        if ( EXT_RES.equals(type) ) {
            renderer = new StreamRenderer(index, indexFiles, getServletContext());
        } else if ( EXT_HTML.equals(type) ) {
            renderer = new HtmlRenderer(xssApi);
        } else if ( EXT_TXT.equals(type) ) {
            renderer = new PlainTextRenderer();
        } else if (EXT_JSON.equals(type) ) {
            renderer = new JsonRenderer(jsonMaximumResults, enableEcmaSupport);
        } else if ( EXT_XML.equals(type) ) {
            renderer = new XMLRenderer();
        }
        return renderer;
    }

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

        // use the Renderer for rendering EXT_RES as the
        // streamer renderer
        Renderer streamRenderer = getDefaultRenderer(EXT_RES);

        rendererMap.put(null, streamRenderer);
        
        rendererMap.put(EXT_RES, streamRenderer);
        
        if (enableHtml) {
            rendererMap.put(EXT_HTML,
                    getDefaultRenderer(EXT_HTML));
        }

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

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

        if (enableXml) {
            rendererMap.put(EXT_XML,
                    getDefaultRenderer(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);
                    Renderer renderer = rendererMap.get(type);
                    if ( renderer == null ) {
                        renderer = getDefaultRenderer(type);
                    }
                    if (renderer != 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, renderer);
                        }
                    } 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");
        }

        Renderer renderer;
        String ext = request.getRequestPathInfo().getExtension();
        renderer = rendererMap.get(ext);

        // fail if we should not just stream or we cannot support the ext.
        if (renderer == 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 " + renderer.getClass().getName()
                + " to render for extension=" + ext);
        renderer.render(request, response);
    }

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

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

    @Override
    public void destroy() {
        rendererMap.clear();
        super.destroy();
    }
}
