/*******************************************************************************
 * 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.scripting.sightly.compiler;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.scripting.sightly.compiler.backend.BackendCompiler;
import org.apache.sling.scripting.sightly.compiler.commands.CommandStream;
import org.apache.sling.scripting.sightly.impl.compiler.CompilationResultImpl;
import org.apache.sling.scripting.sightly.impl.compiler.CompilerFrontend;
import org.apache.sling.scripting.sightly.impl.compiler.CompilerMessageImpl;
import org.apache.sling.scripting.sightly.impl.compiler.PushStream;
import org.apache.sling.scripting.sightly.impl.compiler.debug.SanityChecker;
import org.apache.sling.scripting.sightly.impl.compiler.frontend.SimpleFrontend;
import org.apache.sling.scripting.sightly.impl.compiler.optimization.CoalescingWrites;
import org.apache.sling.scripting.sightly.impl.compiler.optimization.DeadCodeRemoval;
import org.apache.sling.scripting.sightly.impl.compiler.optimization.SequenceStreamTransformer;
import org.apache.sling.scripting.sightly.impl.compiler.optimization.StreamTransformer;
import org.apache.sling.scripting.sightly.impl.compiler.optimization.SyntheticMapRemoval;
import org.apache.sling.scripting.sightly.impl.compiler.optimization.UnusedVariableRemoval;
import org.apache.sling.scripting.sightly.impl.compiler.optimization.reduce.ConstantFolding;
import org.apache.sling.scripting.sightly.impl.filter.Filter;
import org.apache.sling.scripting.sightly.impl.filter.FormatFilter;
import org.apache.sling.scripting.sightly.impl.filter.I18nFilter;
import org.apache.sling.scripting.sightly.impl.filter.JoinFilter;
import org.apache.sling.scripting.sightly.impl.filter.URIManipulationFilter;
import org.apache.sling.scripting.sightly.impl.filter.XSSFilter;
import org.apache.sling.scripting.sightly.impl.plugin.AttributePlugin;
import org.apache.sling.scripting.sightly.impl.plugin.CallPlugin;
import org.apache.sling.scripting.sightly.impl.plugin.ElementPlugin;
import org.apache.sling.scripting.sightly.impl.plugin.IncludePlugin;
import org.apache.sling.scripting.sightly.impl.plugin.ListPlugin;
import org.apache.sling.scripting.sightly.impl.plugin.Plugin;
import org.apache.sling.scripting.sightly.impl.plugin.RepeatPlugin;
import org.apache.sling.scripting.sightly.impl.plugin.ResourcePlugin;
import org.apache.sling.scripting.sightly.impl.plugin.TemplatePlugin;
import org.apache.sling.scripting.sightly.impl.plugin.TestPlugin;
import org.apache.sling.scripting.sightly.impl.plugin.TextPlugin;
import org.apache.sling.scripting.sightly.impl.plugin.UnwrapPlugin;
import org.apache.sling.scripting.sightly.impl.plugin.UsePlugin;
import org.osgi.service.component.annotations.Component;

/**
 * <p>
 * The {@link SightlyCompiler} interprets a HTL script and transforms it internally into a {@link CommandStream}. The
 * {@link CommandStream} can be fed to a {@link BackendCompiler} for transforming the stream into executable code, either by
 * transpiling the commands to a JVM supported language or by directly executing them.
 * </p>
 */
@Component(
        service = SightlyCompiler.class
)
public final class SightlyCompiler {

    private StreamTransformer optimizer;
    private CompilerFrontend frontend;

    public SightlyCompiler() {
        ArrayList<StreamTransformer> transformers = new ArrayList<>(5);
        transformers.add(ConstantFolding.transformer());
        transformers.add(DeadCodeRemoval.transformer());
        transformers.add(SyntheticMapRemoval.TRANSFORMER);
        transformers.add(UnusedVariableRemoval.TRANSFORMER);
        transformers.add(CoalescingWrites.TRANSFORMER);
        optimizer = new SequenceStreamTransformer(transformers);

        // register plugins
        final List<Plugin> plugins = new ArrayList<>(12);
        plugins.add(new AttributePlugin());
        plugins.add(new CallPlugin());
        plugins.add(new ElementPlugin());
        plugins.add(new IncludePlugin());
        plugins.add(new ListPlugin());
        plugins.add(new RepeatPlugin());
        plugins.add(new ResourcePlugin());
        plugins.add(new TemplatePlugin());
        plugins.add(new TestPlugin());
        plugins.add(new TextPlugin());
        plugins.add(new UnwrapPlugin());
        plugins.add(new UsePlugin());
        Collections.sort(plugins);

        // register filters
        final List<Filter> filters = new ArrayList<>(5);
        filters.add(I18nFilter.getInstance());
        filters.add(FormatFilter.getInstance());
        filters.add(JoinFilter.getInstance());
        filters.add(URIManipulationFilter.getInstance());
        filters.add(XSSFilter.getInstance());
        Collections.sort(filters);

        frontend = new SimpleFrontend(plugins, filters);
    }

    /**
     * Compiles a {@link CompilationUnit}.
     *
     * @param compilationUnit a compilation unit
     * @return the compilation result
     */
    public CompilationResult compile(CompilationUnit compilationUnit) {
        return compile(compilationUnit, null);
    }

    /**
     * Compiles a {@link CompilationUnit}, passing the processed {@link CommandStream} to the provided {@link BackendCompiler}.
     *
     * @param compilationUnit a compilation unit
     * @param backendCompiler the backend compiler
     * @return the compilation result
     */
    public CompilationResult compile(CompilationUnit compilationUnit, BackendCompiler backendCompiler) {
        String scriptName = compilationUnit.getScriptName();
        String scriptSource = null;
        PushStream stream = new PushStream();
        SanityChecker.attachChecker(stream);
        CommandStream optimizedStream = optimizer.transform(stream);
        CompilationResultImpl compilationResult = new CompilationResultImpl(optimizedStream);
        try {
            scriptSource = IOUtils.toString(compilationUnit.getScriptReader());

            //optimizedStream.addHandler(LoggingHandler.INSTANCE);
            if (backendCompiler != null) {
                backendCompiler.handle(optimizedStream);
            }
            frontend.compile(stream, scriptSource);
            for (PushStream.StreamMessage w : stream.getWarnings()) {
                ScriptError warning = getScriptError(scriptSource, w.getCode(), 1, 0, w.getMessage());
                compilationResult.getWarnings().add(new CompilerMessageImpl(scriptName, warning.errorMessage, warning.lineNumber, warning
                        .column));
            }
        } catch (SightlyCompilerException e) {
            ScriptError scriptError = getScriptError(scriptSource, e.getOffendingInput(), e.getLine(), e.getColumn(), e.getMessage());
            compilationResult.getErrors().add(new CompilerMessageImpl(scriptName, scriptError.errorMessage, scriptError.lineNumber,
                    scriptError.column));
        } catch (IOException e) {
            throw new SightlyCompilerException("Unable to read source code from CompilationUnit identifying script " + scriptName, e);
        }
        compilationResult.seal();
        return compilationResult;
    }

    private ScriptError getScriptError(String documentFragment, String offendingInput, int lineOffset, int columnOffset, String message) {
        if (StringUtils.isNotEmpty(offendingInput)) {
            String longestContiguousOffendingSequence = null;
            if (documentFragment.contains(offendingInput)) {
                longestContiguousOffendingSequence = offendingInput;
            } else {
                longestContiguousOffendingSequence = getContiguousOffendingSequence(offendingInput);
            }
            int offendingInputIndex = documentFragment.indexOf(longestContiguousOffendingSequence);
            if (offendingInputIndex > -1) {
                String textBeforeError = documentFragment.substring(0, offendingInputIndex);
                int line = lineOffset;
                int lastNewLineIndex = 0;
                for (String s : new String[] {"\r\n", "\r", "\n"}) {
                    int l = textBeforeError.split(s, -1).length - 1;
                    if (l + lineOffset > line) {
                        line = l + lineOffset;
                        int ix = textBeforeError.lastIndexOf(s);
                        if (ix > 0) {
                            lastNewLineIndex = ix + s.length() - 1;
                        }
                    }
                }
                int column = textBeforeError.substring(lastNewLineIndex).length();
                if (column != columnOffset) {
                    column +=columnOffset;
                }
                return new ScriptError(line, column, longestContiguousOffendingSequence + ": " + message);
            }
        }
        return new ScriptError(lineOffset, columnOffset, message);
    }

    private String getContiguousOffendingSequence(String input) {
        if (input != null) {
            StringBuilder longestSequence = new StringBuilder();
            char[] inputCharArray = input.toCharArray();
            for (int index = inputCharArray.length - 1; index >= 0; index--) {
                char c = inputCharArray[index];
                if (!Character.isWhitespace(c)) {
                    longestSequence.insert(0, c);
                } else {
                    break;
                }
            }
            return longestSequence.toString();
        }
        return null;
    }

    private static class ScriptError {

        private int lineNumber;
        private int column;
        private String errorMessage;

        ScriptError(int lineNumber, int column, String errorMessage) {
            this.lineNumber = lineNumber;
            this.column = column;
            this.errorMessage = errorMessage;
        }
    }
}
