/*
 * 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.ranger.plugin.resourcematcher;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOCase;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
import org.apache.ranger.plugin.util.ServiceDefUtil;


public abstract class RangerAbstractResourceMatcher implements RangerResourceMatcher {
	private static final Log LOG = LogFactory.getLog(RangerAbstractResourceMatcher.class);

	public final static String WILDCARD_ASTERISK = "*";

	public final static String OPTION_IGNORE_CASE = "ignoreCase";
	public final static String OPTION_WILD_CARD   = "wildCard";
	public final static String OPTION_REPLACE_TOKENS         = "replaceTokens";
	public final static String OPTION_TOKEN_DELIMITER_START  = "tokenDelimiterStart";
	public final static String OPTION_TOKEN_DELIMITER_END    = "tokenDelimiterEnd";
	public final static String OPTION_TOKEN_DELIMITER_ESCAPE = "tokenDelimiterEscape";
	public final static String OPTION_TOKEN_DELIMITER_PREFIX = "tokenDelimiterPrefix";

	protected RangerResourceDef    resourceDef    = null;
	protected RangerPolicyResource policyResource = null;

	protected boolean      optIgnoreCase = false;
	protected boolean      optWildCard   = false;

	protected List<String> policyValues = null;
	protected boolean policyIsExcludes = false;
	protected boolean isMatchAny = false;
	protected ResourceMatcherWrapper resourceMatchers = null;

	protected boolean optReplaceTokens   = false;
	protected char    startDelimiterChar = '{';
	protected char    endDelimiterChar   = '}';
	protected char    escapeChar         = '\\';
	protected String  tokenPrefix        = "";

	@Override
	public void setResourceDef(RangerResourceDef resourceDef) {
		this.resourceDef = resourceDef;
	}

	@Override
	public void setPolicyResource(RangerPolicyResource policyResource) {
		this.policyResource = policyResource;
	}

	@Override
	public void init() {
		if(LOG.isDebugEnabled()) {
			LOG.debug("==> RangerAbstractResourceMatcher.init()");
		}

		Map<String, String> options = resourceDef != null ? resourceDef.getMatcherOptions() : null;

		optIgnoreCase = getOptionIgnoreCase(options);
		optWildCard   = getOptionWildCard(options);

		policyValues = new ArrayList<String>();
		policyIsExcludes = policyResource == null ? false : policyResource.getIsExcludes();

		if (policyResource != null && policyResource.getValues() != null) {
			for (String policyValue : policyResource.getValues()) {
				if (StringUtils.isEmpty(policyValue)) {
					continue;
				}
				policyValues.add(policyValue);
			}
		}

		optReplaceTokens = getOptionReplaceTokens(options);

		if(optReplaceTokens) {
			startDelimiterChar = getOptionDelimiterStart(options);
			endDelimiterChar   = getOptionDelimiterEnd(options);
			escapeChar         = getOptionDelimiterEscape(options);
			tokenPrefix        = getOptionDelimiterPrefix(options);

			if(escapeChar == startDelimiterChar || escapeChar == endDelimiterChar ||
					tokenPrefix.indexOf(escapeChar) != -1 || tokenPrefix.indexOf(startDelimiterChar) != -1 ||
					tokenPrefix.indexOf(endDelimiterChar) != -1) {
				String resouceName = resourceDef == null ? "" : resourceDef.getName();

				String msg = "Invalid token-replacement parameters for resource '" + resouceName + "': { ";
				msg += (OPTION_TOKEN_DELIMITER_START + "='" + startDelimiterChar + "'; ");
				msg += (OPTION_TOKEN_DELIMITER_END + "='" + endDelimiterChar + "'; ");
				msg += (OPTION_TOKEN_DELIMITER_ESCAPE + "='" + escapeChar + "'; ");
				msg += (OPTION_TOKEN_DELIMITER_PREFIX + "='" + tokenPrefix + "' }. ");
				msg += "Token replacement disabled";

				LOG.error(msg);

				optReplaceTokens = false;
			}
		}

		resourceMatchers = buildResourceMatchers();
		isMatchAny = resourceMatchers == null || CollectionUtils.isEmpty(resourceMatchers.getResourceMatchers());

		if(LOG.isDebugEnabled()) {
			LOG.debug("<== RangerAbstractResourceMatcher.init()");
		}
	}

	@Override
	public boolean isMatchAny() { return isMatchAny; }

	public boolean getNeedsDynamicEval() {
		return resourceMatchers != null && resourceMatchers.getNeedsDynamicEval();
	}

	public static boolean getOptionIgnoreCase(Map<String, String> options) {
		return ServiceDefUtil.getBooleanOption(options, OPTION_IGNORE_CASE, true);
	}

	public static boolean getOptionWildCard(Map<String, String> options) {
		return ServiceDefUtil.getBooleanOption(options, OPTION_WILD_CARD, true);
	}

	public static boolean getOptionReplaceTokens(Map<String, String> options) {
		return ServiceDefUtil.getBooleanOption(options, OPTION_REPLACE_TOKENS, true);
	}

	public static char getOptionDelimiterStart(Map<String, String> options) {
		return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_START, '{');
	}

	public static char getOptionDelimiterEnd(Map<String, String> options) {
		return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_END, '}');
	}

	public static char getOptionDelimiterEscape(Map<String, String> options) {
		return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_ESCAPE, '\\');
	}

	public static String getOptionDelimiterPrefix(Map<String, String> options) {
		return ServiceDefUtil.getOption(options, OPTION_TOKEN_DELIMITER_PREFIX, "");
	}
	protected ResourceMatcherWrapper buildResourceMatchers() {
		List<ResourceMatcher> resourceMatchers = new ArrayList<ResourceMatcher>();
		boolean needsDynamicEval = false;

		for (String policyValue : policyValues) {
			ResourceMatcher matcher = getMatcher(policyValue);

			if (matcher != null) {
				if (matcher.isMatchAny()) {
					resourceMatchers.clear();
					break;
				}
				if (!needsDynamicEval && matcher.getNeedsDynamicEval()) {
					needsDynamicEval = true;
				}
				resourceMatchers.add(matcher);
			}
		}

		Collections.sort(resourceMatchers);

		return CollectionUtils.isNotEmpty(resourceMatchers) ?
				new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null;
	}

	@Override
	public boolean isCompleteMatch(String resource, Map<String, Object> evalContext) {
		if(LOG.isDebugEnabled()) {
			LOG.debug("==> RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + ")");
		}

		boolean ret = false;

		if(CollectionUtils.isEmpty(policyValues)) {
			ret = StringUtils.isEmpty(resource);
		} else if(policyValues.size() == 1) {
			String policyValue = policyValues.get(0);

			if(isMatchAny) {
				ret = StringUtils.containsOnly(resource, WILDCARD_ASTERISK);
			} else {
				ret = optIgnoreCase ? StringUtils.equalsIgnoreCase(resource, policyValue) : StringUtils.equals(resource, policyValue);
			}

			if(policyIsExcludes) {
				ret = !ret;
			}
		}

		if(LOG.isDebugEnabled()) {
			LOG.debug("<== RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + "): " + ret);
		}

		return ret;
	}

	@Override
	public String toString( ) {
		StringBuilder sb = new StringBuilder();

		toString(sb);

		return sb.toString();
	}

	public StringBuilder toString(StringBuilder sb) {
		sb.append("RangerAbstractResourceMatcher={");

		sb.append("resourceDef={");
		if(resourceDef != null) {
			resourceDef.toString(sb);
		}
		sb.append("} ");
		sb.append("policyResource={");
		if(policyResource != null) {
			policyResource.toString(sb);
		}
		sb.append("} ");
		sb.append("optIgnoreCase={").append(optIgnoreCase).append("} ");
		sb.append("optWildCard={").append(optWildCard).append("} ");

		sb.append("policyValues={");
		if(policyValues != null) {
			for(String value : policyValues) {
				sb.append(value).append(",");
			}
		}
		sb.append("} ");

		sb.append("policyIsExcludes={").append(policyIsExcludes).append("} ");
		sb.append("isMatchAny={").append(isMatchAny).append("} ");

		sb.append("options={");
		if(resourceDef != null && resourceDef.getMatcherOptions() != null) {
			for(Map.Entry<String, String> e : resourceDef.getMatcherOptions().entrySet()) {
				sb.append(e.getKey()).append("=").append(e.getValue()).append(';');
			}
		}
		sb.append("} ");

		sb.append("}");

		return sb;
	}

	boolean isAllValuesRequested(String resource) {
		boolean result = StringUtils.isEmpty(resource) || WILDCARD_ASTERISK.equals(resource);
		if (LOG.isDebugEnabled()) {
			LOG.debug("isAllValuesRequested(" + resource + "): " + result);
		}
		return result;
	}

	/**
	 * The only case where excludes flag does NOT change the result is the following:
	 * - Resource denotes all possible values (i.e. resource in (null, "", "*")
	 * - where as policy does not allow all possible values (i.e. policy.values().contains("*")
	 *
     */
	public boolean applyExcludes(boolean allValuesRequested, boolean resultWithoutExcludes) {
		if (!policyIsExcludes) return resultWithoutExcludes;                   // not an excludes policy!
		if (allValuesRequested && !isMatchAny)  return resultWithoutExcludes;  // one case where excludes has no effect
		return !resultWithoutExcludes;                                         // all other cases flip it
	}

	ResourceMatcher getMatcher(String policyValue) {
		final int len = policyValue != null ? policyValue.length() : 0;

		if (len == 0) {
			return null;
		}

		final ResourceMatcher ret;

		int wildcardStartIdx = -1;
		int wildcardEndIdx = -1;
		boolean needWildcardMatch = false;

		// If optWildcard is true
		//   If ('?' found or non-contiguous '*'s found in policyValue)
		//	   needWildcardMatch = true
		// 	 End
		//
		// 	 wildcardStartIdx is set to index of first '*' in policyValue or -1 if '*' is not found in policyValue, and
		// 	 wildcardEndIdx is set to index of last '*' in policyValue or -1 if '*' is not found in policyValue
		// Else
		// 	 needWildcardMatch is set to false
		// End
		if (optWildCard) {
			for (int i = 0; i < len; i++) {
				final char c = policyValue.charAt(i);

				if (c == '?') {
					needWildcardMatch = true;
					break;
				} else if (c == '*') {
					if (wildcardEndIdx == -1 || wildcardEndIdx == (i - 1)) {
						wildcardEndIdx = i;
						if (wildcardStartIdx == -1) {
							wildcardStartIdx = i;
						}
					} else {
						needWildcardMatch = true;
						break;
					}
				}
			}
		}

		if (needWildcardMatch) {
			ret = optIgnoreCase ? new CaseInsensitiveWildcardMatcher(policyValue) : new CaseSensitiveWildcardMatcher(policyValue);
		} else if (wildcardStartIdx == -1) {
			ret = optIgnoreCase ? new CaseInsensitiveStringMatcher(policyValue) : new CaseSensitiveStringMatcher(policyValue);
		} else if (wildcardStartIdx == 0) {
			String matchStr = policyValue.substring(wildcardEndIdx + 1);
			ret = optIgnoreCase ? new CaseInsensitiveEndsWithMatcher(matchStr) : new CaseSensitiveEndsWithMatcher(matchStr);
		} else {
			String matchStr = policyValue.substring(0, wildcardStartIdx);
			ret = optIgnoreCase ? new CaseInsensitiveStartsWithMatcher(matchStr) : new CaseSensitiveStartsWithMatcher(matchStr);
		}

		if(optReplaceTokens) {
			ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix);
		}

		return ret;
	}
}

final class CaseSensitiveStringMatcher extends ResourceMatcher {
	CaseSensitiveStringMatcher(String value) {
		super(value);
	}

	@Override
	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
		return StringUtils.equals(resourceValue, getExpandedValue(evalContext));
	}
	int getPriority() { return 1 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
}

final class CaseInsensitiveStringMatcher extends ResourceMatcher {
	CaseInsensitiveStringMatcher(String value) { super(value); }

	@Override
	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
		return StringUtils.equalsIgnoreCase(resourceValue, getExpandedValue(evalContext));
	}
	int getPriority() {return 2 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}

final class CaseSensitiveStartsWithMatcher extends ResourceMatcher {
	CaseSensitiveStartsWithMatcher(String value) {
		super(value);
	}

	@Override
	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
		return StringUtils.startsWith(resourceValue, getExpandedValue(evalContext));
	}
	int getPriority() { return 3 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);}
}

final class CaseInsensitiveStartsWithMatcher extends ResourceMatcher {
	CaseInsensitiveStartsWithMatcher(String value) { super(value); }

	@Override
	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
		return StringUtils.startsWithIgnoreCase(resourceValue, getExpandedValue(evalContext));
	}
	int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}

final class CaseSensitiveEndsWithMatcher extends ResourceMatcher {
	CaseSensitiveEndsWithMatcher(String value) {
		super(value);
	}

	@Override
	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
		return StringUtils.endsWith(resourceValue, getExpandedValue(evalContext));
	}
	int getPriority() { return 3 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}

final class CaseInsensitiveEndsWithMatcher extends ResourceMatcher {
	CaseInsensitiveEndsWithMatcher(String value) {
		super(value);
	}

	@Override
	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
		return StringUtils.endsWithIgnoreCase(resourceValue, getExpandedValue(evalContext));
	}
	int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}

final class CaseSensitiveWildcardMatcher extends ResourceMatcher {
	CaseSensitiveWildcardMatcher(String value) {
		super(value);
	}

	@Override
	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
		return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), IOCase.SENSITIVE);
	}
	int getPriority() { return 5 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}


final class CaseInsensitiveWildcardMatcher extends ResourceMatcher {
	CaseInsensitiveWildcardMatcher(String value) {
		super(value);
	}

	@Override
	boolean isMatch(String resourceValue, Map<String, Object> evalContext) {
		return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), IOCase.INSENSITIVE);
	}
	int getPriority() {return 6 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); }
}

final class ResourceMatcherWrapper {
	private final boolean needsDynamicEval;
	private final List<ResourceMatcher> resourceMatchers;

	ResourceMatcherWrapper() {
		this(false, null);
	}

	ResourceMatcherWrapper(boolean needsDynamicEval, List<ResourceMatcher> resourceMatchers) {
		this.needsDynamicEval = needsDynamicEval;
		this.resourceMatchers = resourceMatchers;
	}

	boolean getNeedsDynamicEval() {
		return needsDynamicEval;
	}

	List<ResourceMatcher> getResourceMatchers() {
		return resourceMatchers;
	}
}

