/*
 * 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.views.jsp;

import com.opensymphony.xwork2.ActionContext;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.views.jsp.ui.AbstractUITag;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.*;


/**
 */
public abstract class AbstractUITagTest extends AbstractTagTest {

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

    static final String FREEMARKER_ERROR_EXPECTATION = "Java backtrace for programmers:";

    /**
     * Simple helper class for generic tag property testing mechanism. Basically it holds a property name, a property
     * value and an output to be expected in tag output when property was accordingly set.
     *
     * @author <a href="mailto:gielen@it-neering.net">Rene Gielen</a>
     */
    public class PropertyHolder {
        String name, value, expectation;

        public String getName() {
            return name;
        }

        public String getValue() {
            return value;
        }

        public String getExpectation() {
            return expectation;
        }

        /**
         * Construct simple holder with default expectation.
         *
         * @param name  The property name to use.
         * @param value The property value to set.
         * @see #PropertyHolder(String, String, String)
         */
        public PropertyHolder(String name, String value) {
            this(name, value, null);
        }

        /**
         * Construct property holder.
         *
         * @param name        The property name to use.
         * @param value       The property value to set.
         * @param expectation The expected String to occur in tag output caused by setting given tag property. If
         *                    <tt>null</tt>, will be set to <pre>name + "=\"" + value + "\"</pre>.
         */
        public PropertyHolder(String name, String value, String expectation) {
            this.name = name;
            this.value = value;
            if (expectation != null) {
                this.expectation = expectation;
            } else {
                this.expectation = name + "=\"" + value + "\"";
            }
        }

        /**
         * Convenience method for easily adding anonymous constructed instance to a given map, with {@link #getName()}
         * as key.
         *
         * @param map The map to place this instance in.
         */
        public void addToMap(Map<String, PropertyHolder> map) {
            if (map != null) {
                map.put(this.name, this);
            }
        }
    }

    /**
     * Initialize a map of {@link PropertyHolder} for generic tag property testing. Will be used when calling {@link
     * #verifyGenericProperties(org.apache.struts2.views.jsp.ui.AbstractUITag, String, String[])} as properties to
     * verify.<br> This implementation defines testdata for all common AbstractUITag properties and may be overridden in
     * subclasses.
     *
     * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()}
     *         as key.
     */
    protected Map<String, PropertyHolder> initializedGenericTagTestProperties() {
        Map<String, PropertyHolder> result = new HashMap<String, PropertyHolder>();
        new PropertyHolder("name", "someName").addToMap(result);
        new PropertyHolder("id", "someId").addToMap(result);
        new PropertyHolder("cssClass", "cssClass1", "class=\"cssClass1\"").addToMap(result);
        new PropertyHolder("cssStyle", "cssStyle1", "style=\"cssStyle1\"").addToMap(result);
        new PropertyHolder("title", "someTitle").addToMap(result);
        new PropertyHolder("disabled", "true", "disabled=\"disabled\"").addToMap(result);
        //new PropertyHolder("label", "label", "label=\"label\"").addToMap(result);
        //new PropertyHolder("required", "someTitle").addToMap(result);
        new PropertyHolder("tabindex", "99").addToMap(result);
        new PropertyHolder("value", "someValue").addToMap(result);
        new PropertyHolder("onclick", "onclick1").addToMap(result);
        new PropertyHolder("ondblclick", "ondblclick1").addToMap(result);
        new PropertyHolder("onmousedown", "onmousedown1").addToMap(result);
        new PropertyHolder("onmouseup", "onmouseup1").addToMap(result);
        new PropertyHolder("onmouseover", "onmouseover1").addToMap(result);
        new PropertyHolder("onmousemove", "onmousemove1").addToMap(result);
        new PropertyHolder("onmouseout", "onmouseout1").addToMap(result);
        new PropertyHolder("onfocus", "onfocus1").addToMap(result);
        new PropertyHolder("onblur", "onblur1").addToMap(result);
        new PropertyHolder("onkeypress", "onkeypress1").addToMap(result);
        new PropertyHolder("onkeydown", "onkeydown1").addToMap(result);
        new PropertyHolder("onkeyup", "onkeyup1").addToMap(result);
        new PropertyHolder("onclick", "onclick1").addToMap(result);
        new PropertyHolder("onselect", "onchange").addToMap(result);
        return result;
    }

    /**
     * Do a generic verification that setting certain properties on a tag causes expected output regarding this
     * property. In most cases you would not call this directly, instead use {@link
     * #verifyGenericProperties(org.apache.struts2.views.jsp.ui.AbstractUITag, String, String[])}.
     *
     * @param tag              The fresh created tag instance to test.
     * @param theme            The theme to use. If <tt>null</tt>, use configured default theme.
     * @param propertiesToTest Map of {@link PropertyHolder}s, defining properties to test.
     * @param exclude          Names of properties to exclude from particular test.
     * @throws Exception
     */
    public void verifyGenericProperties(AbstractUITag tag, String theme, Map<String, PropertyHolder> propertiesToTest, String[] exclude) throws Exception {
        if (tag != null && propertiesToTest != null) {
            List excludeList;
            if (exclude != null) {
                excludeList = Arrays.asList(exclude);
            } else {
                excludeList = Collections.EMPTY_LIST;
            }

            tag.setPageContext(pageContext);
            if (theme != null) {
                tag.setTheme(theme);
            }

            for (PropertyHolder propertyHolder : propertiesToTest.values()) {
                if (!excludeList.contains(propertyHolder.getName())) {
                    BeanUtils.setProperty(tag, propertyHolder.getName(), propertyHolder.getValue());
                }
            }
            tag.doStartTag();
            tag.doEndTag();
            String writerString = normalize(writer.toString(), true);
            LOG.debug("AbstractUITagTest - [verifyGenericProperties]: Tag output is {}", writerString);

            assertFalse("Freemarker error detected in tag output: " + writerString, writerString.contains(normalize(FREEMARKER_ERROR_EXPECTATION)));

            for (PropertyHolder propertyHolder : propertiesToTest.values()) {
                if (!excludeList.contains(propertyHolder.getName())) {
                    assertTrue("Expected to find: " + propertyHolder.getExpectation() + " in resulting String: " + writerString, writerString.contains(propertyHolder.getExpectation()));
                }
            }
        }
    }

    /**
     * Do a generic verification that setting certain properties on a tag causes expected output regarding this
     * property. Which properties to test with which expectations will be determined by the Map retrieved by {@link #initializedGenericTagTestProperties()}.
     *
     * @param tag     The fresh created tag instance to test.
     * @param theme   The theme to use. If <tt>null</tt>, use configured default theme.
     * @param exclude Names of properties to exclude froObjectm particular test.
     * @throws Exception
     */
    public void verifyGenericProperties(AbstractUITag tag, String theme, String[] exclude) throws Exception {
        verifyGenericProperties(tag, theme, initializedGenericTagTestProperties(), exclude);
    }

    /**
     * Attempt to verify the contents of this.writer against the contents of the resource specified.  verify() performs a
     * trim on both ends
     *
     * @param resource the HTML snippet that we want to validate against
     * @throws Exception if the validation failed
     */
    public void verifyResource(String resource) throws Exception {
        verify(this.getClass().getResource(resource));
    }

    /**
     * Attempt to verify the contents of this.writer against the contents of the URL specified.  verify() performs a
     * trim on both ends
     *
     * @param url the HTML snippet that we want to validate against
     * @throws Exception if the validation failed
     */
    public void verify(URL url) throws Exception {
        if (url == null) {
            fail("unable to verify a null URL");
        } else if (this.writer == null) {
            fail("AbstractJspWriter.writer not initialized.  Unable to verify");
        }

        StringBuilder buffer = new StringBuilder(128);
        try (InputStream in = url.openStream()) {
	        byte[] buf = new byte[4096];
	        int nbytes;
	
	        while ((nbytes = in.read(buf)) > 0) {
	            buffer.append(new String(buf, 0, nbytes));
	        }
        }

        /**
         * compare the trimmed values of each buffer and make sure they're equivalent.  however, let's make sure to
         * normalize the strings first to account for line termination differences between platforms.
         */
        String writerString = normalize(writer.toString(), true);
        String bufferString = normalize(buffer.toString(), true);

        assertEquals(bufferString, writerString);
    }

    protected void setUp() throws Exception {
        super.setUp();

        ServletActionContext.setServletContext(pageContext.getServletContext());
    }

    protected void tearDown() throws Exception {
        super.tearDown();
        ActionContext.setContext(null);
    }

    /**
     * normalizes a string so that strings generated on different platforms can be compared.  any group of one or more
     * space, tab, \r, and \n characters are converted to a single space character
     *
     * @param obj the object to be normalized.  normalize will perform its operation on obj.toString().trim() ;
     * @return the normalized string
     */
    public static String normalize(Object obj) {
        return normalize(obj, false);
    }

    /**
     * normalizes a string so that strings generated on different platforms can be compared.  any group of one or more
     * space, tab, \r, and \n characters are converted to a single space character
     *
     * @param obj         the object to be normalized.  normalize will perform its operation on obj.toString().trim() ;
     * @param appendSpace
     * @return the normalized string
     */
    public static String normalize(Object obj, boolean appendSpace) {
        StringTokenizer st = new StringTokenizer(obj.toString().trim(), " \t\r\n");
        StringBuilder buffer = new StringBuilder(128);

        while (st.hasMoreTokens()) {
            buffer.append(st.nextToken());

            /*
            if (appendSpace && st.hasMoreTokens()) {
                buffer.append("");
            }
            */
        }

        return buffer.toString();
    }
}
