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

import static org.apache.sling.api.scripting.SlingBindings.LOG;
import static org.apache.sling.api.scripting.SlingBindings.OUT;
import static org.apache.sling.api.scripting.SlingBindings.READER;
import static org.apache.sling.api.scripting.SlingBindings.REQUEST;
import static org.apache.sling.api.scripting.SlingBindings.RESOURCE;
import static org.apache.sling.api.scripting.SlingBindings.RESPONSE;
import static org.apache.sling.api.scripting.SlingBindings.SLING;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

import javax.script.SimpleBindings;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.models.factory.ExportException;
import org.apache.sling.models.factory.MissingExporterException;
import org.apache.sling.models.factory.ModelFactory;
import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
import org.apache.sling.scripting.core.ScriptHelper;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("serial")
class ExportServlet extends SlingSafeMethodsServlet {

    private static final String APPLICATION_JSON = "application/json";
    private static final String UTF_8 = "UTF-8";

    private final Logger logger;

    private final String exporterName;
    private final String registeredSelector;
    private final BundleContext bundleContext;
    private final ModelFactory modelFactory;
    private final BindingsValuesProvidersByContext bindingsValuesProvidersByContext;
    private final SlingModelsScriptEngineFactory scriptEngineFactory;
    private final ExportedObjectAccessor accessor;
    private final Map<String, String> baseOptions;

    public ExportServlet(BundleContext bundleContext, ModelFactory modelFactory,
                         BindingsValuesProvidersByContext bindingsValuesProvidersByContext, SlingModelsScriptEngineFactory scriptFactory,
                         Class<?> annotatedClass, String registeredSelector, String exporterName, ExportedObjectAccessor accessor,
                         Map<String, String> baseOptions) {
        this.bundleContext = bundleContext;
        this.modelFactory = modelFactory;
        this.bindingsValuesProvidersByContext = bindingsValuesProvidersByContext;
        this.scriptEngineFactory = scriptFactory;
        this.registeredSelector = registeredSelector;
        this.exporterName = exporterName;
        this.accessor = accessor;
        this.baseOptions = baseOptions;

        String loggerName = ExportServlet.class.getName() + "." + annotatedClass.getName();
        this.logger = LoggerFactory.getLogger(loggerName);
    }

    @Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
            throws ServletException, IOException {
        String contentType = request.getResponseContentType();
        response.setContentType(contentType);

        // workaround for SLING-7344
        if (APPLICATION_JSON.equals(contentType)) {
            response.setCharacterEncoding(UTF_8);
        }

        Map<String, String> options = createOptionMap(request);

        ScriptHelper scriptHelper = new ScriptHelper(bundleContext, null, request, response);

        try {
            addScriptBindings(scriptHelper, request, response);
            String exported;
            try {
                exported = accessor.getExportedString(request, options, modelFactory, exporterName);
            } catch (ExportException e) {
                logger.error("Could not perform export with " + exporterName + " requested by model.", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            } catch (MissingExporterException e) {
                logger.error("Could not get exporter " + exporterName + " requested by model.", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }
            if (exported == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            response.getWriter().write(exported);
        } finally {
            scriptHelper.cleanup();
        }
    }

    private void addScriptBindings(SlingScriptHelper scriptHelper, SlingHttpServletRequest request, SlingHttpServletResponse response)
            throws IOException {
        SimpleBindings bindings = new SimpleBindings();
        bindings.put(SLING, scriptHelper);
        bindings.put(RESOURCE, request.getResource());
        bindings.put(SlingModelsScriptEngineFactory.RESOLVER, request.getResource().getResourceResolver());
        bindings.put(REQUEST, request);
        bindings.put(RESPONSE, response);
        try {
            bindings.put(READER, request.getReader());
        } catch (Exception e) {
            bindings.put(READER, new BufferedReader(new StringReader("")));
        }
        bindings.put(OUT, response.getWriter());
        bindings.put(LOG, logger);

        scriptEngineFactory.invokeBindingsValuesProviders(bindingsValuesProvidersByContext, bindings);

        SlingBindings slingBindings = new SlingBindings();
        slingBindings.putAll(bindings);

        request.setAttribute(SlingBindings.class.getName(), slingBindings);

    }

    @SuppressWarnings("unchecked")
    private Map<String, String> createOptionMap(SlingHttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        String[] selectors = request.getRequestPathInfo().getSelectors();
        Map<String, String> result = new HashMap<String, String>(baseOptions.size() + parameterMap.size() + selectors.length - 1);
        result.putAll(baseOptions);
        for (String selector : selectors) {
            if (!selector.equals(registeredSelector)) {
                result.put(selector, "true");
            }
        }

        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            if (entry.getValue().length == 0) {
                result.put(entry.getKey(), Boolean.TRUE.toString());
            } else {
                result.put(entry.getKey(), entry.getValue()[0]);
            }
        }
        return result;
    }

    public interface ExportedObjectAccessor {
        String getExportedString(SlingHttpServletRequest request, Map<String, String> options, ModelFactory modelFactory, String exporterName) throws ExportException, MissingExporterException;
    }

    public static final class ResourceAccessor implements ExportedObjectAccessor {

        private final Class<?> adapterClass;

        public ResourceAccessor(Class<?> adapterClass) {
            this.adapterClass = adapterClass;
        }

        @Override
        public String getExportedString(SlingHttpServletRequest request, Map<String, String> options, ModelFactory modelFactory, String exporterName) throws ExportException, MissingExporterException {
            Object adapter = modelFactory.createModel(request.getResource(), adapterClass);
            return modelFactory.exportModel(adapter, exporterName, String.class, options);
        }
    }

    public static final class RequestAccessor implements ExportedObjectAccessor {

        private final Class<?> adapterClass;

        public RequestAccessor(Class<?> adapterClass) {
            this.adapterClass = adapterClass;
        }

        @Override
        public String getExportedString(SlingHttpServletRequest request, Map<String, String> options, ModelFactory modelFactory, String exporterName) throws ExportException, MissingExporterException {
            Object adapter = modelFactory.createModel(request, adapterClass);
            return modelFactory.exportModel(adapter, exporterName, String.class, options);
        }
    };

}
