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

import java.io.StringReader;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.freemarker.onlinetester.util.LengthLimitExceededException;
import org.apache.freemarker.onlinetester.util.LengthLimitedWriter;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import freemarker.core.Environment;
import freemarker.core.FreeMarkerInternalsAccessor;
import freemarker.core.OutputFormat;
import freemarker.core.ParseException;
import freemarker.core.TemplateClassResolver;
import freemarker.core.TemplateConfiguration;
import freemarker.template.AttemptExceptionReporter;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

public class FreeMarkerService {

    private static final int DEFAULT_MAX_OUTPUT_LENGTH = 100000;
    private static final int DEFAULT_MAX_THREADS = Math.max(2,
            (int) Math.round(Runtime.getRuntime().availableProcessors() * 3.0 / 4));
    private static final long DEFAULT_MAX_TEMPLATE_EXECUTION_TIME = 2000;
    private static final int MIN_DEFAULT_MAX_QUEUE_LENGTH = 2;
    private static final int MAX_DEFAULT_MAX_QUEUE_LENGTH_MILLISECONDS = 30000;
    private static final long THREAD_KEEP_ALIVE_TIME = 4 * 1000;
    private static final long ABORTION_LOOP_TIME_LIMIT = 5000;
    private static final long ABORTION_LOOP_INTERRUPTION_DISTANCE = 50;
    private static final long THREAD_STOP_EFFECT_WAIT_TIME = 500;
    
    private static final String MAX_OUTPUT_LENGTH_EXCEEDED_TERMINATION = "\n----------\n"
            + "Aborted template processing, as the output length has exceeded the {0} character limit set for "
            + "this service.";
    
    private static final Logger logger = LoggerFactory.getLogger(FreeMarkerService.class);

    private final int maxOutputLength;
    private final int maxThreads;
    private final Integer maxQueueLength;
    private final long maxTemplateExecutionTime;

    private final Configuration freeMarkerConfig;
    private final ExecutorService templateExecutor;
    
    private FreeMarkerService(Builder bulder) {
        maxOutputLength = bulder.getMaxOutputLength();
        maxThreads = bulder.getMaxThreads();
        maxQueueLength = bulder.getMaxQueueLength();
        maxTemplateExecutionTime = bulder.getMaxTemplateExecutionTime();

        int actualMaxQueueLength = maxQueueLength != null
                ? maxQueueLength
                : Math.max(
                        MIN_DEFAULT_MAX_QUEUE_LENGTH,
                        (int) (MAX_DEFAULT_MAX_QUEUE_LENGTH_MILLISECONDS / maxTemplateExecutionTime));
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                maxThreads, maxThreads,
                THREAD_KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS,
                new BlockingArrayQueue<Runnable>(actualMaxQueueLength));
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        templateExecutor = threadPoolExecutor;

        freeMarkerConfig = new Configuration(Configuration.getVersion());
        freeMarkerConfig.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
        freeMarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        freeMarkerConfig.setLogTemplateExceptions(false);
        freeMarkerConfig.setAttemptExceptionReporter(new AttemptExceptionReporter() {
			@Override
			public void report(TemplateException te, Environment env) {
				// Suppress it
			}
        });
        freeMarkerConfig.setLocale(AllowedSettingValuesMaps.DEFAULT_LOCALE);
        freeMarkerConfig.setTimeZone(AllowedSettingValuesMaps.DEFAULT_TIME_ZONE);
        freeMarkerConfig.setOutputFormat(AllowedSettingValuesMaps.DEFAULT_OUTPUT_FORMAT);
        freeMarkerConfig.setOutputEncoding("UTF-8");
    }
    
    /**
     * @param templateSourceCode
     *            The FTL to execute; not {@code null}.
     * @param dataModel
     *            The FreeMarker data-model to execute the template with; maybe {@code null}.
     * @param outputFormat
     *            The output format to execute the template with; maybe {@code null}.
     * @param locale
     *            The locale to execute the template with; maybe {@code null}.
     * @param timeZone
     *            The time zone to execute the template with; maybe {@code null}.
     * 
     * @return The result of the template parsing and evaluation. The method won't throw exception if that fails due to
     *         errors in the template provided, instead it indicates this fact in the response object. That's because
     *         this is a service for trying out the template language, so such errors are part of the normal operation.
     * 
     * @throws RejectedExecutionException
     *             If the service is overburden and thus doing the calculation was rejected.
     * @throws FreeMarkerServiceException
     *             If the calculation fails from a reason that's not a mistake in the template and doesn't fit the
     *             meaning of {@link RejectedExecutionException} either.
     */
    @SuppressWarnings("deprecation") // for Thread.stop()
	public FreeMarkerServiceResponse calculateTemplateOutput(
            String templateSourceCode, Object dataModel, OutputFormat outputFormat, Locale locale, TimeZone timeZone)
            throws RejectedExecutionException {
        Objects.requireNonNull(templateExecutor, "templateExecutor was null - was postConstruct ever called?");
        
        final CalculateTemplateOutput task = new CalculateTemplateOutput(
                templateSourceCode, dataModel, outputFormat, locale, timeZone);
        Future<FreeMarkerServiceResponse> future = templateExecutor.submit(task);
        
        synchronized (task) {
            while (!task.isTemplateExecutionStarted() && !task.isTaskEnded() && !future.isDone()) {
                try {
                    task.wait(50); // Timeout is needed to periodically check future.isDone()
                } catch (InterruptedException e) {
                    throw new FreeMarkerServiceException("Template execution task was interrupted.", e);
                }
            }
        }
        
        try {
            return future.get(maxTemplateExecutionTime, TimeUnit.MILLISECONDS);
        } catch (ExecutionException e) {
            throw new FreeMarkerServiceException("Template execution task unexpectedly failed", e.getCause());
        } catch (InterruptedException e) {
            throw new FreeMarkerServiceException("Template execution task was interrupted.", e);
        } catch (TimeoutException e) {
            // Exactly one interruption should be enough, and it should abort template processing pretty much
            // immediately. But to be on the safe side we will interrupt in a loop, with a timeout.
            final long abortionLoopStartTime = System.currentTimeMillis();
            long timeLeft = ABORTION_LOOP_TIME_LIMIT;
            boolean templateExecutionEnded = false;
            do {
                synchronized (task) {
                    Thread templateExecutorThread = task.getTemplateExecutorThread();
                    if (templateExecutorThread == null) {
                        templateExecutionEnded = true;
                    } else {
                        logger.debug("Trying to interrupt overly long template processing ({} ms left).", timeLeft);
                        FreeMarkerInternalsAccessor.interruptTemplateProcessing(templateExecutorThread);
                    }
                } // sync
                if (!templateExecutionEnded) {
                    try {
                        timeLeft = ABORTION_LOOP_TIME_LIMIT - (System.currentTimeMillis() - abortionLoopStartTime);
                        if (timeLeft > 0) {
                            Thread.sleep(ABORTION_LOOP_INTERRUPTION_DISTANCE);
                        }
                    } catch (InterruptedException eInt) {
                        logger.error("Template execution abortion loop was interrupted", eInt);
                        timeLeft = 0;
                    }
                }
            } while (!templateExecutionEnded && timeLeft > 0);
            
    		// If a slow operation didn't react to Thread.interrupt, we better risk this than allow
    		// the depletion of the thread pool:
            if (!templateExecutionEnded) {
	            synchronized (task) {
	                Thread templateExecutorThread = task.getTemplateExecutorThread();
	                if (templateExecutorThread == null) {
	                    templateExecutionEnded = true;
	                } else {
	                    if (logger.isWarnEnabled()) {
	                    	logger.warn("Calling Thread.stop() on unresponsive long template processing, which didn't "
	                    			+ "respond to Template.interrupt() on time. Service state may will be inconsistent; "
	                    			+ "JVM restart recommended!\n"
	                    			+ "Template (quoted): \"" + StringEscapeUtils.escapeJava(templateSourceCode) + "\"");
	                    }
	                    templateExecutorThread.stop();
	                }
	            } // sync
                try {
                	// We should now receive a result from the task, so that we don't have to die with HTTP 500
					Thread.sleep(THREAD_STOP_EFFECT_WAIT_TIME);
		            synchronized (task) {
		                Thread templateExecutorThread = task.getTemplateExecutorThread();
		                if (templateExecutorThread == null) {
		                    templateExecutionEnded = true;
		                }
		            } // sync
				} catch (InterruptedException e1) {
					// Just continue...
				}
            }
            
            if (templateExecutionEnded) {
                logger.debug("Long template processing has ended.");
                try {
                    return future.get();
                } catch (InterruptedException | ExecutionException e1) {
                    throw new FreeMarkerServiceException("Failed to get result from template executor task", e1);
                }
            } else {
                throw new FreeMarkerServiceException(
                        "Couldn't stop long running template processing within " + ABORTION_LOOP_TIME_LIMIT
                        + " ms. It's possibly stuck forever. Such problems can exhaust the executor pool. "
                        + "Template (quoted): \"" + StringEscapeUtils.escapeJava(templateSourceCode) + "\"");
            }
        }
    }
    
    public int getMaxOutputLength() {
        return maxOutputLength;
    }

    public int getMaxThreads() {
        return maxThreads;
    }
    
    public int getMaxQueueLength() {
        return maxQueueLength;
    }
    
    public long getMaxTemplateExecutionTime() {
        return maxTemplateExecutionTime;
    }

    /**
     * Returns the time zone used by the FreeMarker templates.
     */
    public TimeZone getFreeMarkerTimeZone() {
        return freeMarkerConfig.getTimeZone();
    }
    
    private FreeMarkerServiceResponse createFailureResponse(Throwable e) {
        logger.debug("The template had error(s)", e);
        return new FreeMarkerServiceResponse.Builder().buildForFailure(e);
    }

    private class CalculateTemplateOutput implements Callable<FreeMarkerServiceResponse> {
        
        private boolean templateExecutionStarted;
        private Thread templateExecutorThread;
        private final String templateSourceCode;
        private final Object dataModel;
        private final OutputFormat outputFormat;
        private final Locale locale;
        private final TimeZone timeZone;
        private boolean taskEnded;

        private CalculateTemplateOutput(String templateSourceCode, Object dataModel,
                OutputFormat outputFormat, Locale locale, TimeZone timeZone) {
            this.templateSourceCode = templateSourceCode;
            this.dataModel = dataModel;
            this.outputFormat = outputFormat;
            this.locale = locale;
            this.timeZone = timeZone;
        }
        
        @Override
        public FreeMarkerServiceResponse call() throws Exception {
            try {
                Template template;
                try {
                    TemplateConfiguration tCfg = new TemplateConfiguration();
                    tCfg.setParentConfiguration(freeMarkerConfig);
                    if (outputFormat != null) {
                        tCfg.setOutputFormat(outputFormat);
                    }
                    if (locale != null) {
                        tCfg.setLocale(locale);
                    }
                    if (timeZone != null) {
                        tCfg.setTimeZone(timeZone);
                    }
                    
                    template = new Template(null, null,
                            new StringReader(templateSourceCode), freeMarkerConfig, tCfg, null);
                    
                    tCfg.apply(template);
                } catch (ParseException e) {
                    // Expected (part of normal operation)
                    return createFailureResponse(e);
                } catch (Exception e) {
                    // Not expected
                    throw new FreeMarkerServiceException("Unexpected exception during template parsing", e);
                }
                
                FreeMarkerInternalsAccessor.makeTemplateInterruptable(template);
                
                boolean resultTruncated;
                StringWriter writer = new StringWriter();
                try {
                    synchronized (this) {
                        templateExecutorThread = Thread.currentThread(); 
                        templateExecutionStarted = true;
                        notifyAll();
                    }
                    try {
                        template.process(dataModel, new LengthLimitedWriter(writer, maxOutputLength));
                    } finally {
                        synchronized (this) {
                            templateExecutorThread = null;
                            FreeMarkerInternalsAccessor.clearAnyPendingTemplateProcessingInterruption();
                        }
                    }
                    resultTruncated = false;
                } catch (LengthLimitExceededException e) {
                    // Not really an error, we just cut the output here.
                    resultTruncated = true;
                    writer.write(new MessageFormat(MAX_OUTPUT_LENGTH_EXCEEDED_TERMINATION, AllowedSettingValuesMaps.DEFAULT_LOCALE)
                            .format(new Object[] { maxOutputLength }));
                    // Falls through
                } catch (TemplateException e) {
                    // Expected (part of normal operation)
                    return createFailureResponse(e);
                } catch (Throwable e) {
                    if (FreeMarkerInternalsAccessor.isTemplateProcessingInterruptedException(e)
                    		|| e instanceof ThreadDeath /* due to Thread.stop() */) {
                        return new FreeMarkerServiceResponse.Builder().buildForFailure(new TimeoutException(
                                "Template processing was aborted for exceeding the " + getMaxTemplateExecutionTime()
                                + " ms time limit set for this online service. This is usually because you have "
                                + "a very long running #list (or other kind of loop) in your template.")); 
                    }
                    // Not expected
                    throw new FreeMarkerServiceException("Unexpected exception during template evaluation", e);
                }
                
                return new FreeMarkerServiceResponse.Builder().buildForSuccess(writer.toString(), resultTruncated);
            } finally {
                synchronized (this) {
                    taskEnded = true;
                    notifyAll();
                }
            }
        }
        
        private synchronized boolean isTemplateExecutionStarted() {
            return templateExecutionStarted;
        }

        private synchronized boolean isTaskEnded() {
            return taskEnded;
        }
        
        /**
         * @return non-{@code null} after the task execution has actually started, but before it has finished.
         */
        private synchronized Thread getTemplateExecutorThread() {
            return templateExecutorThread;
        }
        
    }

    public static class Builder {
        private int maxOutputLength = DEFAULT_MAX_OUTPUT_LENGTH;
        private int maxThreads = DEFAULT_MAX_THREADS;
        private Integer maxQueueLength;
        private long maxTemplateExecutionTime = DEFAULT_MAX_TEMPLATE_EXECUTION_TIME;

        public int getMaxOutputLength() {
            return maxOutputLength;
        }

        public void setMaxOutputLength(int maxOutputLength) {
            this.maxOutputLength = maxOutputLength;
        }

        public int getMaxThreads() {
            return maxThreads;
        }

        public void setMaxThreads(int maxThreads) {
            this.maxThreads = maxThreads;
        }

        public Integer getMaxQueueLength() {
            return maxQueueLength;
        }

        public void setMaxQueueLength(Integer maxQueueLength) {
            this.maxQueueLength = maxQueueLength;
        }

        public long getMaxTemplateExecutionTime() {
            return maxTemplateExecutionTime;
        }

        public void setMaxTemplateExecutionTime(long maxTemplateExecutionTime) {
            this.maxTemplateExecutionTime = maxTemplateExecutionTime;
        }

        public FreeMarkerService build() {
            return new FreeMarkerService(this);
        }
    }

}
