/*
 * 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.struts2.components;

import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.util.ComponentUtils;
import org.apache.struts2.util.FastByteArrayOutputStream;
import org.apache.struts2.views.TagAttribute;
import org.apache.struts2.views.annotations.StrutsTagAttribute;
import org.apache.struts2.views.jsp.TagUtils;
import org.apache.struts2.views.util.UrlHelper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Base class to extend for UI components.
 * <br>
 * This class is a good extension point when building reusable UI components.
 *
 */
public class Component {

    private static final Logger LOG = LogManager.getLogger(Component.class);

    public static final String COMPONENT_STACK = "__component_stack";

    /**
     * Caches information about common tag's attributes to reduce scanning for annotation @StrutsTagAttribute
     */
    protected static ConcurrentMap<Class<?>, Collection<String>> standardAttributesMap = new ConcurrentHashMap<>();

    protected boolean devMode = false;
    protected ValueStack stack;
    protected Map<String, Object> parameters;
    protected ActionMapper actionMapper;
    protected boolean throwExceptionOnELFailure;
    private UrlHelper urlHelper;

    /**
     * Constructor.
     *
     * @param stack  OGNL value stack.
     */
    public Component(ValueStack stack) {
        this.stack = stack;
        this.parameters = new LinkedHashMap<>();
        getComponentStack().push(this);
    }

    /**
     * Gets the name of this component.
     * @return the name of this component.
     */
    private String getComponentName() {
        Class c = getClass();
        String name = c.getName();
        int dot = name.lastIndexOf('.');

        return name.substring(dot + 1).toLowerCase();
    }

    @Inject(value = StrutsConstants.STRUTS_DEVMODE, required = false)
    public void setDevMode(String devMode) {
        this.devMode = BooleanUtils.toBoolean(devMode);
    }

    @Inject
    public void setActionMapper(ActionMapper mapper) {
        this.actionMapper = mapper;
    }

    @Inject(StrutsConstants.STRUTS_EL_THROW_EXCEPTION)
    public void setThrowExceptionsOnELFailure(String throwException) {
        this.throwExceptionOnELFailure = BooleanUtils.toBoolean(throwException);
    }

    @Inject
    public void setUrlHelper(UrlHelper urlHelper) {
        this.urlHelper = urlHelper;
    }
    /**
     * Gets the OGNL value stack associated with this component.
     * @return the OGNL value stack associated with this component.
     */
    public ValueStack getStack() {
        return stack;
    }

    /**
     * Gets the component stack of this component.
     * @return the component stack of this component, never <tt>null</tt>.
     */
    public Stack<Component> getComponentStack() {
        Stack<Component> componentStack = (Stack<Component>) stack.getContext().get(COMPONENT_STACK);
        if (componentStack == null) {
            componentStack = new Stack<>();
            stack.getContext().put(COMPONENT_STACK, componentStack);
        }
        return componentStack;
    }

    /**
     * Callback for the start tag of this component.
     * Should the body be evaluated?
     *
     * @param writer  the output writer.
     * @return true if the body should be evaluated
     */
    public boolean start(Writer writer) {
        return true;
    }

    /**
     * Callback for the end tag of this component.
     * Should the body be evaluated again?
     * <br>
     * <b>NOTE:</b> will pop component stack.
     * @param writer  the output writer.
     * @param body    the rendered body.
     * @return true if the body should be evaluated again
     */
    public boolean end(Writer writer, String body) {
        return end(writer, body, true);
    }

    /**
     * Callback for the start tag of this component.
     * Should the body be evaluated again?
     * <br>
     * <b>NOTE:</b> has a parameter to determine to pop the component stack.
     * @param writer  the output writer.
     * @param body    the rendered body.
     * @param popComponentStack  should the component stack be popped?
     * @return true if the body should be evaluated again
     */
    protected boolean end(Writer writer, String body, boolean popComponentStack) {
        assert(body != null);

        try {
            writer.write(body);
        } catch (IOException e) {
            throw new StrutsException("IOError while writing the body: " + e.getMessage(), e);
        }
        if (popComponentStack) {
            popComponentStack();
        }
        return false;
    }

    /**
     * Pops the component stack.
     */
    protected void popComponentStack() {
        getComponentStack().pop();
    }

    /**
     * Finds the nearest ancestor of this component stack.
     * @param clazz the class to look for, or if assignable from.
     * @return  the component if found, <tt>null</tt> if not.
     */
    protected Component findAncestor(Class clazz) {
        Stack componentStack = getComponentStack();
        int currPosition = componentStack.search(this);
        if (currPosition >= 0) {
            int start = componentStack.size() - currPosition - 1;

            //for (int i = componentStack.size() - 2; i >= 0; i--) {
            for (int i = start; i >=0; i--) {
                Component component = (Component) componentStack.get(i);
                if (clazz.isAssignableFrom(component.getClass()) && component != this) {
                    return component;
                }
            }
        }

        return null;
    }

    /**
     * Evaluates the OGNL stack to find a String value.
     * @param expr  OGNL expression.
     * @return  the String value found.
     */
    protected String findString(String expr) {
        return (String) findValue(expr, String.class);
    }

    protected TagAttribute findString(TagAttribute attribute) {
        return findValue(attribute, String.class);
    }

    /**
     * Evaluates the OGNL stack to find a String value.
     * <br>
     * If the given expression is <tt>null</tt> a error is logged and a <code>RuntimeException</code> is thrown
     * constructed with a messaged based on the given field and errorMsg parameter.
     *
     * @param expr  OGNL expression.
     * @param field   field name used when throwing <code>RuntimeException</code>.
     * @param errorMsg  error message used when throwing <code>RuntimeException</code>.
     * @return  the String value found.
     * @throws StrutsException is thrown in case of expression is null.
     */
    protected String findString(String expr, String field, String errorMsg) {
        if (expr == null) {
            throw fieldError(field, errorMsg, null);
        } else {
            return findString(expr);
        }
    }

    /**
     * Constructs a <code>RuntimeException</code> based on the given information.
     * <br>
     * A message is constructed and logged at ERROR level before being returned
     * as a <code>RuntimeException</code>.
     * @param field   field name used when throwing <code>RuntimeException</code>.
     * @param errorMsg  error message used when throwing <code>RuntimeException</code>.
     * @param e  the caused exception, can be <tt>null</tt>.
     * @return  the constructed <code>StrutsException</code>.
     */
    protected StrutsException fieldError(String field, String errorMsg, Exception e) {
        String msg = "tag '" + getComponentName() + "', field '" + field +
                ( parameters != null && parameters.containsKey("name")?"', name '" + parameters.get("name"):"") +
                "': " + errorMsg;
        throw new StrutsException(msg, e);
    }

    /**
     * Finds a value from the OGNL stack based on the given expression.
     * Will always evaluate <code>expr</code> against stack except when <code>expr</code>
     * is null. If altsyntax (%{...}) is applied, simply strip it off.
     *
     * @param expr  the expression. Returns <tt>null</tt> if expr is null.
     * @return the value, <tt>null</tt> if not found.
     */
    protected Object findValue(String expr) {
        if (expr == null) {
            return null;
        }

        expr = stripExpressionIfAltSyntax(expr);

        return getStack().findValue(expr, throwExceptionOnELFailure);
    }

    /**
     * If altsyntax (%{...}) is applied, simply strip the "%{" and "}" off.
     * @param expr the expression (must be not null)
     * @return the stripped expression if altSyntax is enabled. Otherwise
     * the parameter expression is returned as is.
     */
	protected String stripExpressionIfAltSyntax(String expr) {
		return ComponentUtils.stripExpressionIfAltSyntax(stack, expr);
	}

    /**
     * See <code>struts.properties</code> where the altSyntax flag is defined.
     * @return if the altSyntax enabled? [TRUE]
     */
    public boolean altSyntax() {
        return ComponentUtils.altSyntax(stack);
    }

    /**
     * Adds the surrounding %{ } to the expression for proper processing.
     * @param expr the expression.
     * @return the modified expression if altSyntax is enabled, or the parameter
     * expression otherwise.
     */
	protected String completeExpressionIfAltSyntax(String expr) {
		if (altSyntax()) {
			return "%{" + expr + "}";
		}
		return expr;
	}

    /**
     * This check is needed for backwards compatibility with 2.1.x
     * @param expr the expression.
     * @return the found string if altSyntax is enabled. The parameter
     * expression otherwise.
     */
	protected String findStringIfAltSyntax(String expr) {
		if (altSyntax()) {
		    return findString(expr);
		}
		return expr;
	}

    protected TagAttribute findStringIfAltSyntax(TagAttribute attribute) {
        if (altSyntax()) {
            return findString(attribute);
        }
        return attribute;
    }

    /**
     * <p>
     * Evaluates the OGNL stack to find an Object value.
     * </p>
     *
     * <p>
     * Function just like <code>findValue(String)</code> except that if the
     * given expression is <tt>null</tt> a error is logged and
     * a <code>RuntimeException</code> is thrown constructed with a
     * messaged based on the given field and errorMsg parameter.
     * </p>
     *
     * @param expr  OGNL expression.
     * @param field   field name used when throwing <code>RuntimeException</code>.
     * @param errorMsg  error message used when throwing <code>RuntimeException</code>.
     * @return  the Object found, is never <tt>null</tt>.
     * @throws StrutsException is thrown in case of not found in the OGNL stack, or expression is <tt>null</tt>.
     */
    protected Object findValue(String expr, String field, String errorMsg) {
        if (expr == null) {
            throw fieldError(field, errorMsg, null);
        } else {
            Object value = null;
            Exception problem = null;
            try {
                value = findValue(expr);
            } catch (Exception e) {
                problem = e;
            }

            if (value == null) {
                throw fieldError(field, errorMsg, problem);
            }

            return value;
        }
    }

    /**
     * Evaluates the OGNL stack to find an Object of the given type. Will evaluate
     * <code>expr</code> the portion wrapped with altSyntax (%{...})
     * against stack when altSyntax is on, else the whole <code>expr</code>
     * is evaluated against the stack.
     * <br>
     * This method only supports the altSyntax. So this should be set to true.
     * @param expr  OGNL expression.
     * @param toType  the type expected to find.
     * @return  the Object found, or <tt>null</tt> if not found.
     */
    protected Object findValue(String expr, Class<?> toType) {
        if (altSyntax() && toType == String.class) {
            if (ComponentUtils.containsExpression(expr)) {
                return TextParseUtil.translateVariables('%', expr, stack);
            } else {
                return expr;
            }
        } else {
            expr = stripExpressionIfAltSyntax(expr);

            return getStack().findValue(expr, toType, throwExceptionOnELFailure);
        }
    }

    protected TagAttribute findValue(TagAttribute attribute, Class<?> toType) {
        if (altSyntax() && toType == String.class) {
            if (attribute.isExpression() && !attribute.isEvaluated()) {
                String translateVariables = TextParseUtil.translateVariables('%', attribute.getValue(), stack);
                return TagAttribute.evaluated(translateVariables);
            } else {
                return attribute;
            }
        } else {
            Object value = getStack().findValue(attribute.stripedExpression(), toType, throwExceptionOnELFailure);

            if (value == null) {
                return TagAttribute.NULL;
            } else {
                return TagAttribute.evaluated(String.valueOf(value));
            }
        }
    }

    /**
     * Renders an action URL by consulting the {@link org.apache.struts2.dispatcher.mapper.ActionMapper}.
     * @param action      the action
     * @param namespace   the namespace
     * @param method      the method
     * @param req         HTTP request
     * @param res         HTTP response
     * @param parameters  parameters
     * @param scheme      http or https
     * @param includeContext  should the context path be included or not
     * @param encodeResult    should the url be encoded
     * @param forceAddSchemeHostAndPort    should the scheme host and port be forced
     * @param escapeAmp    should ampersand (&amp;) be escaped to &amp;amp;
     * @return the action url.
     */
    protected String determineActionURL(String action, String namespace, String method,
                                        HttpServletRequest req, HttpServletResponse res, Map parameters, String scheme,
                                        boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort,
                                        boolean escapeAmp) {
        String finalAction = findString(action);
        String finalMethod = method != null ? findString(method) : null;
        String finalNamespace = determineNamespace(namespace, getStack(), req);
        ActionMapping mapping = new ActionMapping(finalAction, finalNamespace, finalMethod, parameters);
        String uri = actionMapper.getUriFromActionMapping(mapping);
        return urlHelper.buildUrl(uri, req, res, parameters, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, escapeAmp);
    }

    /**
     * Determines the namespace of the current page being renderdd. Useful for Form, URL, and href generations.
     * @param namespace  the namespace
     * @param stack      OGNL value stack
     * @param req        HTTP request
     * @return  the namepsace of the current page being rendered, is never <tt>null</tt>.
     */
    protected String determineNamespace(String namespace, ValueStack stack, HttpServletRequest req) {
        String result;

        if (namespace == null) {
            result = TagUtils.buildNamespace(actionMapper, stack, req);
        } else {
            result = findString(namespace);
        }

        if (result == null) {
            result = "";
        }

        return result;
    }

    /**
     * Pushes this component's parameter Map as well as the component itself on to the stack
     * and then copies the supplied parameters over. Because the component's parameter Map is
     * pushed before the component itself, any key-value pair that can't be assigned to component
     * will be set in the parameters Map.
     *
     * @param params  the parameters to copy.
     */
    public void copyParams(Map<String, ?> params) {
        stack.push(parameters);
        stack.push(this);
        try {
            for (Map.Entry<String, ?> entry : params.entrySet()) {
                String key = entry.getKey();

                if (key.indexOf('-') >= 0) {
                    // UI component attributes may contain hypens (e.g. data-ajax), but ognl
                    // can't handle that, and there can't be a component property with a hypen
                    // so into the parameters map it goes. See WW-4493
                    parameters.put(key, entry.getValue());
                } else {
                    stack.setValue(key, entry.getValue());
                }
            }
        } finally {
            stack.pop();
            stack.pop();
        }
    }

    /**
     * Constructs a string representation of the given exception.
     * @param t  the exception
     * @return the exception as a string.
     */
    protected String toString(Throwable t) {
        try (FastByteArrayOutputStream bout = new FastByteArrayOutputStream();
                PrintWriter wrt = new PrintWriter(bout)) {
            t.printStackTrace(wrt);
            return bout.toString();
        }
    }

    /**
     * Gets the parameters.
     * @return the parameters. Is never <tt>null</tt>.
     */
    public Map<String, Object> getParameters() {
        return parameters;
    }

    /**
     * Adds all the given parameters to this component's own parameters.
     * @param params the parameters to add.
     */
    public void addAllParameters(Map params) {
        parameters.putAll(params);
    }

    /**
     * Adds the given key and value to this component's own parameter.
     * <br>
     * If the provided key is <tt>null</tt> nothing happens.
     * If the provided value is <tt>null</tt> any existing parameter with
     * the given key name is removed.
     * @param key  the key of the new parameter to add.
     * @param value the value associated with the key.
     */
    public void addParameter(String key, Object value) {
        if (key != null) {
            Map params = getParameters();

            if (value == null) {
                params.remove(key);
            } else {
                params.put(key, value);
            }
        }
    }

    /**
     * Overwrite to set if body should be used.
     * @return always false for this component.
     */
    public boolean usesBody() {
        return false;
    }

    /**
     * Override to set if body content should be HTML-escaped.
     *
     * @return always true (default) for this component.
     *
     * @since 2.6
     */
    public boolean escapeHtmlBody() {
        return true;
    }

    /**
     * Checks if provided name is a valid tag's attribute
     *
     * @param attrName String name of attribute
     * @return true if attribute with the same name was already defined
     */
    public boolean isValidTagAttribute(String attrName) {
        return getStandardAttributes().contains(attrName);
    }

    /**
     * If needed caches all methods annotated by given annotation to avoid further scans
     *
     * @return list of attributes
     */
    protected Collection<String> getStandardAttributes() {
        Class clz = getClass();
        Collection<String> standardAttributes = standardAttributesMap.get(clz);
        if (standardAttributes == null) {
            Collection<Method> methods = MethodUtils.getMethodsListWithAnnotation(clz, StrutsTagAttribute.class,
                    true, true);
            standardAttributes = new HashSet<>(methods.size());
            for(Method m : methods) {
                standardAttributes.add(StringUtils.uncapitalize(m.getName().substring(3)));
            }
            standardAttributesMap.putIfAbsent(clz, standardAttributes);
        }
        return standardAttributes;
    }

}
