/*******************************************************************************
 * Copyright (c) 2008, 2020 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Connexta, LLC - performance improvements
 *******************************************************************************/
package org.eclipse.osgi.internal.permadmin;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.Permission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.osgi.framework.Bundle;
import org.osgi.service.condpermadmin.Condition;
import org.osgi.service.condpermadmin.ConditionInfo;
import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
import org.osgi.service.permissionadmin.PermissionInfo;

public final class SecurityRow implements ConditionalPermissionInfo {
	/* Used to find condition constructors getConditions */
	static final Class<?>[] conditionMethodArgs = new Class[] {Bundle.class, ConditionInfo.class};
	static Condition[] ABSTAIN_LIST = new Condition[0];
	static Condition[] SATISFIED_LIST = new Condition[0];
	static final Decision DECISION_ABSTAIN = new Decision(SecurityTable.ABSTAIN, null, null, null);
	static final Decision DECISION_GRANTED = new Decision(SecurityTable.GRANTED, null, null, null);
	static final Decision DECISION_DENIED = new Decision(SecurityTable.DENIED, null, null, null);

	private final SecurityAdmin securityAdmin;
	private final String name;
	private final ConditionInfo[] conditionInfos;
	private final PermissionInfoCollection permissionInfoCollection;
	private final boolean deny;
	/* GuardedBy(bundleConditions) */
	final Map<BundlePermissions, Condition[]> bundleConditions;
	final Object bundleConditionsLock = new Object();

	public SecurityRow(SecurityAdmin securityAdmin, String name, ConditionInfo[] conditionInfos, PermissionInfo[] permissionInfos, String decision) {
		if (permissionInfos == null || permissionInfos.length == 0)
			throw new IllegalArgumentException("It is invalid to have empty permissionInfos"); //$NON-NLS-1$
		this.securityAdmin = securityAdmin;
		this.conditionInfos = conditionInfos == null ? new ConditionInfo[0] : conditionInfos;
		decision = decision.toLowerCase();
		boolean d = ConditionalPermissionInfo.DENY.equals(decision);
		boolean a = ConditionalPermissionInfo.ALLOW.equals(decision);
		if (!(d | a))
			throw new IllegalArgumentException("Invalid decision: " + decision); //$NON-NLS-1$
		this.deny = d;
		this.name = name;
		this.permissionInfoCollection = new PermissionInfoCollection(permissionInfos);
		if (conditionInfos == null || conditionInfos.length == 0)
			bundleConditions = null;
		else
			bundleConditions = new HashMap<>();
	}

	static SecurityRowSnapShot createSecurityRowSnapShot(String encoded) {
		return (SecurityRowSnapShot) createConditionalPermissionInfo(null, encoded);
	}

	static SecurityRow createSecurityRow(SecurityAdmin securityAdmin, String encoded) {
		return (SecurityRow) createConditionalPermissionInfo(securityAdmin, encoded);
	}

	private static ConditionalPermissionInfo createConditionalPermissionInfo(SecurityAdmin securityAdmin, String encoded) {
		encoded = encoded.trim();
		if (encoded.length() == 0)
			throw new IllegalArgumentException("Empty encoded string is invalid"); //$NON-NLS-1$
		char[] chars = encoded.toCharArray();
		int end = encoded.length() - 1;
		char lastChar = chars[end];
		if (lastChar != '}' && lastChar != '"')
			throw new IllegalArgumentException(encoded);
		String encodedName = null;
		if (lastChar == '"') {
			// we have a name: an empty name must have at least 2 chars for the quotes
			if (chars.length < 2)
				throw new IllegalArgumentException(encoded);
			int endName = encoded.length() - 1;
			int startName = endName - 1;
			while (startName > 0) {
				if (chars[startName] == '"') {
					startName--;
					if (startName > 0 && chars[startName] == '\\')
						startName--;
					else {
						startName++;
						break;
					}
				}
				startName--;
			}
			if (chars[startName] != '"')
				throw new IllegalArgumentException(encoded);
			encodedName = unescapeString(encoded.substring(startName + 1, endName));
			end = encoded.lastIndexOf('}', startName);
		}
		int start = encoded.indexOf('{');
		if (start < 0 || end < start)
			throw new IllegalArgumentException(encoded);

		String decision = encoded.substring(0, start);
		decision = decision.trim();
		if (decision.length() == 0 || (!ConditionalPermissionInfo.DENY.equalsIgnoreCase(decision) && !ConditionalPermissionInfo.ALLOW.equalsIgnoreCase(decision)))
			throw new IllegalArgumentException(encoded);

		List<ConditionInfo> condList = new ArrayList<>();
		List<PermissionInfo> permList = new ArrayList<>();
		int pos = start + 1;
		while (pos < end) {
			while (pos < end && chars[pos] != '[' && chars[pos] != '(')
				pos++;
			if (pos == end)
				break; // no perms or conds left
			int startPos = pos;
			char endChar = chars[startPos] == '[' ? ']' : ')';
			while (pos < end && chars[pos] != endChar) {
				if (chars[pos] == '"') {
					pos++;
					while (chars[pos] != '"') {
						if (chars[pos] == '\\')
							pos++;
						pos++;
					}
				}
				pos++;
			}
			int endPos = pos;
			String token = new String(chars, startPos, endPos - startPos + 1);
			if (endChar == ']')
				condList.add(new ConditionInfo(token));
			else
				permList.add(new PermissionInfo(token));
			pos++;
		}
		if (permList.size() == 0)
			throw new IllegalArgumentException("No Permission infos: " + encoded); //$NON-NLS-1$
		ConditionInfo[] conds = condList.toArray(new ConditionInfo[condList.size()]);
		PermissionInfo[] perms = permList.toArray(new PermissionInfo[permList.size()]);
		if (securityAdmin == null)
			return new SecurityRowSnapShot(encodedName, conds, perms, decision);
		return new SecurityRow(securityAdmin, encodedName, conds, perms, decision);
	}

	static Object cloneArray(Object[] array) {
		if (array == null)
			return null;
		Object result = Array.newInstance(array.getClass().getComponentType(), array.length);
		System.arraycopy(array, 0, result, 0, array.length);
		return result;
	}

	private static void escapeString(String str, StringBuilder output) {
		int len = str.length();
		for (int i = 0; i < len; i++) {
			char c = str.charAt(i);
			switch (c) {
				case '"' :
				case '\\' :
					output.append('\\');
					output.append(c);
					break;
				case '\r' :
					output.append("\\r"); //$NON-NLS-1$
					break;
				case '\n' :
					output.append("\\n"); //$NON-NLS-1$
					break;
				default :
					output.append(c);
					break;
			}
		}
	}

	private static String unescapeString(String str) {
		StringBuilder output = new StringBuilder(str.length());
		int end = str.length();
		for (int i = 0; i < end; i++) {
			char c = str.charAt(i);
			if (c == '\\') {
				i++;
				if (i < end) {
					c = str.charAt(i);
					switch (c) {
						case '"' :
						case '\\' :
							break;
						case 'r' :
							c = '\r';
							break;
						case 'n' :
							c = '\n';
							break;
						default :
							c = '\\';
							i--;
							break;
					}
				}
			}
			output.append(c);
		}

		return output.toString();
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public ConditionInfo[] getConditionInfos() {
		// must make a copy for the public API method to prevent modification
		return (ConditionInfo[]) cloneArray(conditionInfos);
	}

	ConditionInfo[] internalGetConditionInfos() {
		return conditionInfos;
	}

	@Override
	public String getAccessDecision() {
		return deny ? ConditionalPermissionInfo.DENY : ConditionalPermissionInfo.ALLOW;
	}

	@Override
	public PermissionInfo[] getPermissionInfos() {
		// must make a copy for the public API method to prevent modification
		return (PermissionInfo[]) cloneArray(permissionInfoCollection.getPermissionInfos());
	}

	PermissionInfo[] internalGetPermissionInfos() {
		return permissionInfoCollection.getPermissionInfos();
	}

	/**
	 * @deprecated
	 */
	@Override
	public void delete() {
		securityAdmin.delete(this, true);
	}

	Condition[] getConditions(BundlePermissions bundlePermissions) {
		synchronized (bundleConditionsLock) {
			Condition[] conditions = null;
			if (bundleConditions != null) {
				conditions = bundleConditions.get(bundlePermissions);
			}
			if (conditions == null) {
				conditions = new Condition[conditionInfos.length];
				for (int i = 0; i < conditionInfos.length; i++) {
					/*
					 * TODO: Can we pre-get the Constructors in our own constructor
					 */
					Class<?> clazz;
					try {
						clazz = Class.forName(conditionInfos[i].getType());
					} catch (ClassNotFoundException e) {
						/* If the class isn't there, we fail */
						return null;
					}
					Constructor<?> constructor = null;
					Method method = getConditionMethod(clazz);
					if (method == null) {
						constructor = getConditionConstructor(clazz);
						if (constructor == null) {
							// TODO should post a FrameworkEvent of type error here
							conditions[i] = Condition.FALSE;
							continue;
						}
					}

					Object[] args = {bundlePermissions.getBundle(), conditionInfos[i]};
					try {
						if (method != null)
							conditions[i] = (Condition) method.invoke(null, args);
						else
							conditions[i] = (Condition) constructor.newInstance(args);
					} catch (Exception e) {
						// TODO should post a FrameworkEvent of type error here
						conditions[i] = Condition.FALSE;
					}
				}
				if (bundleConditions != null) {
					bundleConditions.put(bundlePermissions, conditions);
				}
			}
			return conditions;
		}
	}

	private Method getConditionMethod(Class<?> clazz) {
		for (Method checkMethod : clazz.getMethods()) {
			if (checkMethod.getName().equals("getCondition") //$NON-NLS-1$
					&& (checkMethod.getModifiers() & Modifier.STATIC) == Modifier.STATIC //
					&& checkParameterTypes(checkMethod.getParameterTypes())) {
				return checkMethod;
			}
		}
		return null;
	}

	private Constructor<?> getConditionConstructor(Class<?> clazz) {
		for (Constructor<?> checkConstructor : clazz.getConstructors()) {
			if (checkParameterTypes(checkConstructor.getParameterTypes())) {
				return checkConstructor;
			}
		}
		return null;
	}

	private boolean checkParameterTypes(Class<?>[] foundTypes) {
		if (foundTypes.length != conditionMethodArgs.length) {
			return false;
		}

		for (int i = 0; i < foundTypes.length; i++) {
			if (!foundTypes[i].isAssignableFrom(conditionMethodArgs[i])) {
				return false;
			}
		}
		return true;
	}

	Decision evaluate(BundlePermissions bundlePermissions, Permission permission) {
		if (bundleConditions == null || bundlePermissions == null)
			return evaluatePermission(bundlePermissions, permission);
		Condition[] conditions = getConditions(bundlePermissions);
		if (conditions == ABSTAIN_LIST)
			return DECISION_ABSTAIN;
		if (conditions == SATISFIED_LIST)
			return evaluatePermission(bundlePermissions, permission);

		boolean empty = true;
		List<Condition> postponedConditions = null;
		Decision postponedPermCheck = null;
		for (int i = 0; i < conditions.length; i++) {
			Condition condition = conditions[i];
			if (condition == null)
				continue; // this condition must have been satisfied && !mutable in a previous check
			if (!isPostponed(condition)) {
				// must call isMutable before calling isSatisfied according to the specification.
				boolean mutable = condition.isMutable();
				if (condition.isSatisfied()) {
					if (!mutable)
						conditions[i] = null; // ignore this condition for future checks
				} else {
					if (!mutable)
						// this will cause the row to always abstain; mark this to be ignored in future checks
						synchronized (bundleConditionsLock) {
							bundleConditions.put(bundlePermissions, ABSTAIN_LIST);
						}
					return DECISION_ABSTAIN;
				}
			} else { // postponed case
				if (postponedPermCheck == null)
					// perform a permission check now
					postponedPermCheck = evaluatePermission(bundlePermissions, permission);
				if (postponedPermCheck == DECISION_ABSTAIN)
					return postponedPermCheck; // no need to postpone the condition if the row abstains
				// this row will deny or allow the permission; must queue the postponed condition
				if (postponedConditions == null)
					postponedConditions = new ArrayList<>(1);
				postponedConditions.add(condition);
			}
			empty &= conditions[i] == null;
		}
		if (empty) {
			synchronized (bundleConditionsLock) {
				bundleConditions.put(bundlePermissions, SATISFIED_LIST);
			}
		}
		if (postponedPermCheck != null)
			return new Decision(postponedPermCheck.decision | SecurityTable.POSTPONED, postponedConditions.toArray(new Condition[postponedConditions.size()]), this, bundlePermissions);
		return evaluatePermission(bundlePermissions, permission);
	}

	private boolean isPostponed(Condition condition) {
		// postponed checks can only happen if we are using a supported security manager
		return condition.isPostponed() && securityAdmin.getSupportedSecurityManager() != null;
	}

	private Decision evaluatePermission(BundlePermissions bundlePermissions, Permission permission) {
		return permissionInfoCollection.implies(bundlePermissions, permission) ? (deny ? DECISION_DENIED : DECISION_GRANTED) : DECISION_ABSTAIN;
	}

	@Override
	public String toString() {
		return getEncoded();
	}

	@Override
	public String getEncoded() {
		return getEncoded(name, conditionInfos, internalGetPermissionInfos(), deny);
	}

	@Override
	public boolean equals(Object obj) {
		// doing the simple (slow) thing for now
		if (obj == this)
			return true;
		if (!(obj instanceof ConditionalPermissionInfo))
			return false;
		// we assume the encoded string provides a canonical (comparable) form
		return getEncoded().equals(((ConditionalPermissionInfo) obj).getEncoded());
	}

	@Override
	public int hashCode() {
		return getHashCode(name, internalGetConditionInfos(), internalGetPermissionInfos(), getAccessDecision());
	}

	static int getHashCode(String name, ConditionInfo[] conds, PermissionInfo[] perms, String decision) {
		int h = 31 * 17 + decision.hashCode();
		for (ConditionInfo cond : conds) {
			h = 31 * h + cond.hashCode();
		}
		for (PermissionInfo perm : perms) {
			h = 31 * h + perm.hashCode();
		}
		if (name != null)
			h = 31 * h + name.hashCode();
		return h;
	}

	static String getEncoded(String name, ConditionInfo[] conditionInfos, PermissionInfo[] permissionInfos, boolean deny) {
		StringBuilder result = new StringBuilder();
		if (deny)
			result.append(ConditionalPermissionInfo.DENY);
		else
			result.append(ConditionalPermissionInfo.ALLOW);
		result.append(" { "); //$NON-NLS-1$
		if (conditionInfos != null)
			for (ConditionInfo conditionInfo : conditionInfos) {
				result.append(conditionInfo.getEncoded()).append(' ');
			}
		if (permissionInfos != null)
			for (PermissionInfo permissionInfo : permissionInfos) {
				result.append(permissionInfo.getEncoded()).append(' ');
			}
		result.append('}');
		if (name != null) {
			result.append(" \""); //$NON-NLS-1$
			escapeString(name, result);
			result.append('"');
		}
		return result.toString();
	}

	PermissionInfoCollection getPermissionInfoCollection() {
		return permissionInfoCollection;
	}

	void clearCaches() {
		permissionInfoCollection.clearPermissionCache();
		if (bundleConditions != null)
			synchronized (bundleConditionsLock) {
				bundleConditions.clear();
			}
	}

	static class Decision {
		final int decision;
		final Condition[] postponed;
		private final SecurityRow row;
		private final BundlePermissions bundlePermissions;

		Decision(int decision, Condition[] postponed, SecurityRow row, BundlePermissions bundlePermissions) {
			this.decision = decision;
			this.postponed = postponed;
			this.row = row;
			this.bundlePermissions = bundlePermissions;
		}

		void handleImmutable(Condition condition, boolean isSatisfied, boolean mutable) {
			if (mutable || !condition.isPostponed())
				return; // do nothing
			if (isSatisfied) {
				synchronized (row.bundleConditionsLock) {
					Condition[] rowConditions = row.bundleConditions.get(bundlePermissions);
					boolean isEmpty = true;
					for (int i = 0; i < rowConditions.length; i++) {
						if (rowConditions[i] == condition)
							if (isSatisfied)
								rowConditions[i] = null;
						isEmpty &= rowConditions[i] == null;
					}
					if (isEmpty)
						row.bundleConditions.put(bundlePermissions, SATISFIED_LIST);
				}
			} else {
				synchronized (row.bundleConditionsLock) {
					row.bundleConditions.put(bundlePermissions, ABSTAIN_LIST);
				}
			}
		}
	}
}
