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

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.scripting.sightly.compiler.SightlyCompilerException;
import org.apache.sling.scripting.sightly.compiler.commands.Conditional;
import org.apache.sling.scripting.sightly.compiler.commands.OutText;
import org.apache.sling.scripting.sightly.compiler.commands.OutputVariable;
import org.apache.sling.scripting.sightly.compiler.commands.VariableBinding;
import org.apache.sling.scripting.sightly.compiler.expression.Expression;
import org.apache.sling.scripting.sightly.compiler.expression.ExpressionNode;
import org.apache.sling.scripting.sightly.compiler.expression.MarkupContext;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperation;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperator;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.BooleanConstant;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.Identifier;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.RuntimeCall;
import org.apache.sling.scripting.sightly.compiler.expression.nodes.StringConstant;
import org.apache.sling.scripting.sightly.impl.compiler.Patterns;
import org.apache.sling.scripting.sightly.impl.compiler.PushStream;
import org.apache.sling.scripting.sightly.impl.compiler.Syntax;
import org.apache.sling.scripting.sightly.impl.compiler.frontend.CompilerContext;
import org.apache.sling.scripting.sightly.impl.compiler.frontend.ElementContext;
import org.apache.sling.scripting.sightly.impl.compiler.frontend.ExpressionParser;
import org.apache.sling.scripting.sightly.impl.compiler.frontend.ExpressionWrapper;
import org.apache.sling.scripting.sightly.impl.compiler.frontend.Fragment;
import org.apache.sling.scripting.sightly.impl.compiler.frontend.Interpolation;
import org.apache.sling.scripting.sightly.impl.compiler.util.SymbolGenerator;
import org.apache.sling.scripting.sightly.impl.filter.ExpressionContext;
import org.apache.sling.scripting.sightly.impl.filter.Filter;
import org.apache.sling.scripting.sightly.impl.html.MarkupUtils;
import org.apache.sling.scripting.sightly.impl.plugin.Plugin;
import org.apache.sling.scripting.sightly.impl.plugin.PluginCallInfo;
import org.apache.sling.scripting.sightly.impl.plugin.PluginInvoke;

/**
 * Implementation for the markup handler
 */
public class MarkupHandler {

    private final PushStream stream;
    private final SymbolGenerator symbolGenerator = new SymbolGenerator();
    private final ExpressionParser expressionParser = new ExpressionParser();
    private final Map<String, Plugin> pluginRegistry;
    private final CompilerContext compilerContext;
    private final ExpressionWrapper expressionWrapper;

    private final Stack<ElementContext> elementStack = new Stack<>();
    private static final Set<String> URI_ATTRIBUTES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("action", "cite",
            "data", "formaction", "href",  "manifest", "poster", "src")));

    public MarkupHandler(PushStream stream, Map<String, Plugin> pluginRegistry, List<Filter> filters) {
        this.stream = stream;
        this.pluginRegistry = pluginRegistry;
        this.expressionWrapper = new ExpressionWrapper(filters);
        this.compilerContext = new CompilerContext(symbolGenerator, expressionWrapper, stream);
    }

    public void onOpenTagStart(String markup, String tagName) {
        ElementContext context = new ElementContext(tagName, markup);
        elementStack.push(context);
    }

    public void onAttribute(String name, String value, char quoteChar) {
        ElementContext context = elementStack.peek();
        if (Syntax.isPluginAttribute(name)) {
            try {
                handlePlugin(name, StringUtils.defaultString(value, ""), context);
            } catch (SightlyCompilerException e) {
                if (StringUtils.isEmpty(e.getOffendingInput()) && StringUtils.isNotEmpty(value)) {
                    throw new SightlyCompilerException(e.getMessage(), name + "=" + quoteChar + value + quoteChar );
                }
                throw e;
            }
        } else {
            context.addAttribute(name, value, quoteChar);
        }
    }

    public void onOpenTagEnd(String markup) {
        ElementContext context = elementStack.peek();
        PluginInvoke invoke = context.pluginInvoke();
        invoke.beforeElement(stream, context.getTagName());
        boolean slyTag = "sly".equalsIgnoreCase(context.getTagName());
        if (slyTag) {
            Patterns.beginStreamIgnore(stream);
        }
        invoke.beforeTagOpen(stream);
        out(context.getOpenTagStartMarkup());
        invoke.beforeAttributes(stream);
        traverseAttributes(context, invoke);
        invoke.afterAttributes(stream);
        out(markup);
        invoke.afterTagOpen(stream);
        if (slyTag) {
            Patterns.endStreamIgnore(stream);
        }
        invoke.beforeChildren(stream);
    }

    private void traverseAttributes(ElementContext context, PluginInvoke invoke) {
        for (ElementContext.Attribute attribute : context.getAttributes()) {
            String attrName = attribute.getName();
            Object contentObj = attribute.getValue();
            if (contentObj == null || contentObj instanceof String) {
                String content = (String) contentObj;
                emitAttribute(attrName, content, attribute.getQuoteChar(), invoke);
            } else if (contentObj instanceof Map.Entry) {
                Map.Entry entry = (Map.Entry) contentObj;
                PluginCallInfo info = (PluginCallInfo) entry.getKey();
                Expression expression = (Expression) entry.getValue();
                invoke.onPluginCall(stream, info, expression);
            }
        }
    }

    private void emitAttribute(String name, String content, char quoteChar, PluginInvoke invoke) {
        invoke.beforeAttribute(stream, name);
        if (content == null) {
            emitSimpleTextAttribute(name, null, quoteChar, invoke);
        } else {
            Interpolation interpolation = expressionParser.parseInterpolation(content);
            String text = tryAsSimpleText(interpolation);
            if (text != null) {
                emitSimpleTextAttribute(name, text, quoteChar, invoke);
            } else {
                emitExpressionAttribute(name, interpolation, quoteChar, invoke);
            }
        }
        invoke.afterAttribute(stream, name);
    }

    private void emitSimpleTextAttribute(String name, String textValue, char quoteChar, PluginInvoke invoke) {
        emitAttributeStart(name);
        invoke.beforeAttributeValue(stream, name, new StringConstant(textValue));
        if (textValue != null) {
            emitAttributeValueStart(quoteChar);
            textValue = escapeQuotes(textValue);
            out(textValue);
            emitAttributeEnd(quoteChar);
        }
        invoke.afterAttributeValue(stream, name);
    }

    private String escapeQuotes(String textValue) {
        return textValue.replace("\"", "&quot;");
    }

    private void emitExpressionAttribute(String name, Interpolation interpolation, char quoteChar, PluginInvoke invoke) {
        interpolation = attributeChecked(name, interpolation);
        if (interpolation.size() == 1) {
            emitSingleFragment(name, interpolation, quoteChar, invoke);
        } else {
            emitMultipleFragment(name, interpolation, quoteChar, invoke);
        }
    }

    private void emitMultipleFragment(String name, Interpolation interpolation, char quoteChar, PluginInvoke invoke) {
        // Simplified algorithm for attribute output, which works when the interpolation is not of size 1. In this
        // case we are certain that the attribute value cannot be the boolean value true, so we can skip this test
        // altogether
        Expression expression = expressionWrapper.transform(interpolation, getAttributeMarkupContext(name), ExpressionContext.ATTRIBUTE);
        String attrContent = symbolGenerator.next("attrContent");
        String shouldDisplayAttr = symbolGenerator.next("shouldDisplayAttr");
        stream.write(new VariableBinding.Start(attrContent, expression.getRoot()));
        stream.write(
                new VariableBinding.Start(
                        shouldDisplayAttr,
                        new BinaryOperation(
                                BinaryOperator.OR,
                                new Identifier(attrContent),
                                new BinaryOperation(BinaryOperator.EQ, new StringConstant("false"), new Identifier(attrContent))
                        )
                )
        );
        stream.write(new Conditional.Start(shouldDisplayAttr, true));
        emitAttributeStart(name);
        invoke.beforeAttributeValue(stream, name, expression.getRoot());
        emitAttributeValueStart(quoteChar);
        stream.write(new OutputVariable(attrContent));
        emitAttributeEnd(quoteChar);
        invoke.afterAttributeValue(stream, name);
        stream.write(Conditional.END);
        stream.write(VariableBinding.END);
        stream.write(VariableBinding.END);
    }

    private void emitSingleFragment(String name, Interpolation interpolation, char quoteChar, PluginInvoke invoke) {
        Expression valueExpression = expressionWrapper.transform(interpolation, null, ExpressionContext.ATTRIBUTE); //raw expression
        String attrValue = symbolGenerator.next("attrValue"); //holds the raw attribute value
        String attrContent = symbolGenerator.next("attrContent"); //holds the escaped attribute value
        String isTrueVar = symbolGenerator.next("isTrueAttr"); // holds the comparison (attrValue == true)
        String shouldDisplayAttr = symbolGenerator.next("shouldDisplayAttr");
        MarkupContext markupContext = getAttributeMarkupContext(name);
        boolean alreadyEscaped = false;
        if (valueExpression.getRoot() instanceof RuntimeCall) {
            RuntimeCall rc = (RuntimeCall) valueExpression.getRoot();
            if (RuntimeCall.XSS.equals(rc.getFunctionName())) {
                alreadyEscaped = true;
            }
        }
        ExpressionNode node = valueExpression.getRoot();
        stream.write(new VariableBinding.Start(attrValue, node)); //attrContent = <expr>
        if (!alreadyEscaped) {
            Expression contentExpression = valueExpression.withNode(new Identifier(attrValue));
            stream.write(new VariableBinding.Start(attrContent, adjustContext(compilerContext, contentExpression, markupContext).getRoot()));
            stream.write(
                    new VariableBinding.Start(
                            shouldDisplayAttr,
                            new BinaryOperation(
                                    BinaryOperator.OR,
                                    new Identifier(attrContent),
                                    new BinaryOperation(BinaryOperator.EQ, new StringConstant("false"), new Identifier(attrValue))
                            )
                    )
            );

        } else {
            stream.write(
                    new VariableBinding.Start(
                            shouldDisplayAttr,
                            new BinaryOperation(
                                    BinaryOperator.OR,
                                    new Identifier(attrValue),
                                    new BinaryOperation(BinaryOperator.EQ, new StringConstant("false"), new Identifier(attrValue))
                            )
                    )
            );
        }
        stream.write(new Conditional.Start(shouldDisplayAttr, true)); // if (attrContent)

        emitAttributeStart(name);   //write("attrName");
        invoke.beforeAttributeValue(stream, name, node);
        stream.write(new VariableBinding.Start(isTrueVar, //isTrueAttr = (attrValue == true)
                new BinaryOperation(BinaryOperator.EQ, new Identifier(attrValue), BooleanConstant.TRUE)));
        stream.write(new Conditional.Start(isTrueVar, false)); //if (!isTrueAttr)
        emitAttributeValueStart(quoteChar); // write("='");
        if (!alreadyEscaped) {
            stream.write(new OutputVariable(attrContent)); //write(attrContent)
        } else {
            stream.write(new OutputVariable(attrValue)); // write(attrValue)
        }
        emitAttributeEnd(quoteChar); //write("'");
        stream.write(Conditional.END); //end if isTrueAttr
        stream.write(VariableBinding.END); //end scope for isTrueAttr
        invoke.afterAttributeValue(stream, name);
        stream.write(Conditional.END); //end if attrContent
        stream.write(VariableBinding.END); //end scope for attrContent
        if (!alreadyEscaped) {
            stream.write(VariableBinding.END);
        }
        stream.write(VariableBinding.END); //end scope for attrValue
    }


    private void emitAttributeStart(String name) {
        out(" " + name);
    }

    private void emitAttributeValueStart(char quoteChar) {
        char quote = '"';
        if (quoteChar != 0) {
            quote = quoteChar;
        }
        out("=");
        out(String.valueOf(quote));
    }

    private void emitAttributeEnd(char quoteChar) {
        char quote = '"';
        if (quoteChar != 0) {
            quote = quoteChar;
        }
        out(String.valueOf(quote));
    }


    public void onCloseTag(String markup) {
        ElementContext context = elementStack.pop();
        PluginInvoke invoke = context.pluginInvoke();
        invoke.afterChildren(stream);
        boolean selfClosingTag = StringUtils.isEmpty(markup);
        boolean slyTag = "sly".equalsIgnoreCase(context.getTagName());
        if (slyTag) {
            Patterns.beginStreamIgnore(stream);
        }
        invoke.beforeTagClose(stream, selfClosingTag);
        out(markup);
        invoke.afterTagClose(stream, selfClosingTag);
        if (slyTag) {
            Patterns.endStreamIgnore(stream);
        }
        invoke.afterElement(stream);
    }


    public void onText(String text) {
        String tag = currentElementTag();
        boolean explicitContextRequired = isExplicitContextRequired(tag);
        MarkupContext markupContext = (explicitContextRequired) ? null : MarkupContext.TEXT;
        outText(text, markupContext);
    }


    public void onComment(String markup) {
        if (!Syntax.isSightlyComment(markup)) {
            outText(markup, MarkupContext.COMMENT);
        }
    }


    public void onDataNode(String markup) {
        out(markup);
    }


    public void onDocType(String markup) {
        out(markup);
    }


    public void onDocumentFinished() {
        this.stream.close();
    }

    private void outText(String content, MarkupContext context) {
        Interpolation interpolation = expressionParser.parseInterpolation(content);
        if (context == null) {
            interpolation = requireContext(interpolation);
        }
        String text = tryAsSimpleText(interpolation);
        if (text != null) {
            out(text);
        } else {
            outExprNode(expressionWrapper.transform(interpolation, context, ExpressionContext.TEXT).getRoot());
        }
    }

    private Interpolation requireContext(Interpolation interpolation) {
        Interpolation result = new Interpolation();
        for (Fragment fragment : interpolation.getFragments()) {
            Fragment addedFragment;
            if (fragment.isString()) {
                addedFragment = fragment;
            } else {
                if (fragment.getExpression().containsOption(Syntax.CONTEXT_OPTION)) {
                    addedFragment = fragment;
                } else {
                    String currentTag = currentElementTag();
                    String warningMessage = String.format("Element %s requires that all expressions have an explicit context specified. " +
                            "The expression will be replaced with an empty string.", currentTag);
                    stream.warn(new PushStream.StreamMessage(warningMessage, fragment.getExpression().getRawText()));
                    addedFragment = new Fragment.Expr(new Expression(StringConstant.EMPTY));
                }
            }
            result.addFragment(addedFragment);
        }
        return result;
    }

    private Interpolation attributeChecked(String attributeName, Interpolation interpolation) {
        if (!MarkupUtils.isSensitiveAttribute(attributeName)) {
            return interpolation;
        }
        Interpolation newInterpolation = new Interpolation();
        for (Fragment fragment : interpolation.getFragments()) {
            Fragment addedFragment = fragment;
            if (fragment.isExpression()) {
                Expression expression = fragment.getExpression();
                if (!expression.containsOption(Syntax.CONTEXT_OPTION)) {
                    String warningMessage = String.format("Expressions within the value of attribute %s need to have an explicit context " +
                            "option. The expression will be replaced with an empty string.", attributeName);
                    stream.warn(new PushStream.StreamMessage(warningMessage, expression.getRawText()));
                    addedFragment = new Fragment.Text("");
                }
            }
            newInterpolation.addFragment(addedFragment);
        }
        return newInterpolation;
    }


    private void outExprNode(ExpressionNode node) {
        String variable = symbolGenerator.next();
        stream.write(new VariableBinding.Start(variable, node));
        stream.write(new OutputVariable(variable));
        stream.write(VariableBinding.END);
    }


    private String tryAsSimpleText(Interpolation interpolation) {
        if (interpolation.size() == 1) {
            Fragment fragment = interpolation.getFragment(0);
            if (fragment.isString()) {
                return fragment.getText();
            }
        } else if (interpolation.size() == 0) {
            return "";
        }
        return null;
    }

    private void out(String text) {
        stream.write(new OutText(text));
    }

    private void handlePlugin(String name, String value, ElementContext context) {
        PluginCallInfo callInfo = Syntax.parsePluginAttribute(name);
        if (callInfo != null) {
            Plugin plugin = obtainPlugin(callInfo.getName());
            ExpressionContext expressionContext = ExpressionContext.getContextForPlugin(plugin.name());
            Expression expr = expressionWrapper.transform(expressionParser.parseInterpolation(value), null, expressionContext);
            PluginInvoke invoke = plugin.invoke(expr, callInfo, compilerContext);
            context.addPlugin(invoke, plugin.priority());
            context.addPluginCall(name, callInfo, expr);
        }
    }

    private Plugin obtainPlugin(String name) {
        Plugin plugin = pluginRegistry.get(name);
        if (plugin == null) {
            throw new SightlyCompilerException(String.format("None of the registered plugins can handle the data-sly-%s block element.",
                    name), "data-sly-" + name);
        }
        return plugin;
    }

    private MarkupContext getAttributeMarkupContext(String attributeName) {
       if (URI_ATTRIBUTES.contains(attributeName.toLowerCase())) {
           return MarkupContext.URI;
       }
        return MarkupContext.ATTRIBUTE;
    }

    private String currentElementTag() {
        if (elementStack.isEmpty()) {
            return null;
        }
        ElementContext current = elementStack.peek();
        return current.getTagName();
    }

    private boolean isExplicitContextRequired(String parentElementName) {
        return parentElementName != null &&
                ("script".equals(parentElementName) || "style".equals(parentElementName));
    }

    private Expression adjustContext(CompilerContext compilerContext, Expression expression, MarkupContext markupContext) {
        ExpressionNode root = expression.getRoot();
        if (root instanceof RuntimeCall) {
            RuntimeCall runtimeCall = (RuntimeCall) root;
            if (runtimeCall.getFunctionName().equals(RuntimeCall.XSS)) {
                return expression;
            }
        }
        return compilerContext.adjustToContext(expression, markupContext, ExpressionContext.ATTRIBUTE);
    }
}
