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

import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.WildcardUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.regex.Pattern;

/**
 * <p>Isolate the process of cleaning JSON data from the Interceptor class
 * itself.</p>
 * 
 * <p>The allowed and blocked wildcard patterns, combined with
 * defaultBlock, let you filter out values that should not be injected, in
 * the same way that ParameterFilterInterceptor does.  Note that you can
 * only remove values from a Map.  Removing values from a List is dangerous
 * because it could change the meaning of the data!</p>
 */
public abstract class JSONCleaner {

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

    public static class Filter
    {
        public Pattern pattern;
        public boolean allow;

        public Filter(String pattern, boolean allow)
        {
            this.pattern = WildcardUtil.compileWildcardPattern(pattern);
            this.allow = allow;
        }
    }

    private boolean defaultBlock = false;
    private Collection<String> allowed;
    private Collection<String> blocked;
    private Map<String, Filter> includesExcludesMap;

    public Object clean(String ognlPrefix, Object data) throws JSONException {
        if (data == null)
            return null;
        else if (data instanceof List)
            return cleanList(ognlPrefix, data);
        else if (data instanceof Map)
            return cleanMap(ognlPrefix, data);
        else
            return cleanValue(ognlPrefix, data);
    }

    protected Object cleanList(String ognlPrefix, Object data) throws JSONException {
        List list = (List) data;
        int count = list.size();
        for (int i = 0; i < count; i++) {
            list.set(i, clean(ognlPrefix + "[" + i + "]", list.get(i)));
        }
        return list;
    }

    protected Object cleanMap(String ognlPrefix, Object data) throws JSONException {
        Map map = (Map) data;
        Iterator iter = map.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry e = (Map.Entry) iter.next();
            String key = (ognlPrefix.length() > 0 ? ognlPrefix + "." : "") + e.getKey();
            if (allow(key)) {
                e.setValue(clean(key, e.getValue()));
            } else {
                LOG.debug("Blocked: {}", key);
                iter.remove();
            }
        }
        return map;
    }

    protected abstract Object cleanValue(String ognlName, Object data) throws JSONException;

    private boolean allow(String ognl) {
        Map<String, Filter> includesExcludesMap = getIncludesExcludesMap();

        boolean allow = !isDefaultBlock();

        if (includesExcludesMap != null) {
            for (Filter f : includesExcludesMap.values()) {
                if (f.pattern.matcher(ognl).matches()) {
                    allow = f.allow;
                }
            }
        }

        return allow;
    }

    /**
     * @return the compiled list of includes and excludes
     */
    public Map<String, Filter> getIncludesExcludesMap() {
        if (allowed == null && blocked == null) {
            return includesExcludesMap;
        }

        if (includesExcludesMap == null) {
            includesExcludesMap = new TreeMap<>();

            Map<String, Boolean> existingExpr = new HashMap<>();

            Map<String, Map<String, String>> includePatternData = JSONUtil.getIncludePatternData();
            String splitPattern = includePatternData.get(JSONUtil.SPLIT_PATTERN).get(JSONUtil.WILDCARD_PATTERN);
            String joinString = includePatternData.get(JSONUtil.JOIN_STRING).get(JSONUtil.WILDCARD_PATTERN);
            String arrayBegin = includePatternData.get(JSONUtil.ARRAY_BEGIN_STRING).get(JSONUtil.WILDCARD_PATTERN);
            String arrayEnd = includePatternData.get(JSONUtil.ARRAY_END_STRING).get(JSONUtil.WILDCARD_PATTERN);

            if (allowed != null) {
                for (String a : allowed) {
                    // Compile a pattern for each level of the object hierarchy
                    // so cleanMap() won't short-circuit too early.

                    String expr = "";
                    for (String piece : a.split(splitPattern)) {
                        if (expr.length() > 0) {
                            expr += joinString;
                        }
                        expr += piece;

                        if (!existingExpr.containsKey(expr)) {
                            existingExpr.put(expr, Boolean.TRUE);

                            String s = expr;
                            if (piece.endsWith(arrayEnd)) {
                                s = expr.substring(0, expr.lastIndexOf(arrayBegin));
                            }

                            if (s.length() > 0) {
                                includesExcludesMap.put(s, new Filter(s, true));

                                LOG.debug("Adding include wildcard expression: {}", s);
                            }
                        }
                    }
                }
            }
            if (blocked != null) {
                for (String b : blocked) {
                    includesExcludesMap.put(b, new Filter(b, false));
                }
            }
        }

        return includesExcludesMap;
    }

    /**
     * Allow external caching of the compiled result.
     *
     * @param map the compiled list of includes and excludes
     */
    public void setIncludesExcludesMap(Map<String, Filter> map) {
        includesExcludesMap = map;
    }

    /**
     * @return value of defaultBlock
     */
    public boolean isDefaultBlock() {
        return defaultBlock;
    }

    /**
     * @param defaultExclude The defaultExclude to set.
     */
    public void setDefaultBlock(boolean defaultExclude) {
        this.defaultBlock = defaultExclude;
    }

    /**
     * @return list of blocked wildcard patterns
     */
    public Collection<String> getBlockedCollection() {
        return blocked;
    }

    /**
     * @param blocked The blocked to set.
     */
    public void setBlockedCollection(Collection<String> blocked) {
        this.blocked = blocked;
    }

    /**
     * @param blocked The blocked parameters as comma separated String.
     */
    public void setBlocked(String blocked) {
        setBlockedCollection(asCollection(blocked));
    }

    /**
     * @return list of allowed wildcard patterns
     */
    public Collection<String> getAllowedCollection() {
        return allowed;
    }

    /**
     * @param allowed The allowed to set.
     */
    public void setAllowedCollection(Collection<String> allowed) {
        this.allowed = allowed;
    }

    /**
     * @param allowed The allowed paramters as comma separated String.
     */
    public void setAllowed(String allowed) {
        setAllowedCollection(asCollection(allowed));
    }

    /**
     * Return a collection from the comma delimited String.
     *
     * @param commaDelim the comma delimited String.
     * @return A collection from the comma delimited String. Returns <tt>null</tt> if the string is empty.
     */
    private Collection<String> asCollection(String commaDelim) {
        if (commaDelim == null || commaDelim.trim().length() == 0) {
            return null;
        }
        return TextParseUtil.commaDelimitedStringToSet(commaDelim);
    }

}
