/*
 * Copyright (C) 2019, Google LLC. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.transport;

import static java.math.BigInteger.ZERO;
import static java.util.Objects.requireNonNull;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_FILTER;

import java.math.BigInteger;
import java.text.MessageFormat;

import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.internal.JGitText;

/**
 * Represents either a filter specified in a protocol "filter" line, or a
 * placeholder to indicate no filtering.
 *
 * @since 5.4
 */
public final class FilterSpec {

	/** Immutable bit-set representation of a set of Git object types. */
	static class ObjectTypes {
		static ObjectTypes ALL = allow(OBJ_BLOB, OBJ_TREE, OBJ_COMMIT, OBJ_TAG);

		private final BigInteger val;

		private ObjectTypes(BigInteger val) {
			this.val = requireNonNull(val);
		}

		static ObjectTypes allow(int... types) {
			BigInteger bits = ZERO;
			for (int type : types) {
				bits = bits.setBit(type);
			}
			return new ObjectTypes(bits);
		}

		boolean contains(int type) {
			return val.testBit(type);
		}

		@Override
		public boolean equals(Object obj) {
			if (!(obj instanceof ObjectTypes)) {
				return false;
			}

			ObjectTypes other = (ObjectTypes) obj;
			return other.val.equals(val);
		}

		@Override
		public int hashCode() {
			return val.hashCode();
		}
	}

	private final ObjectTypes types;

	private final long blobLimit;

	private final long treeDepthLimit;

	private FilterSpec(ObjectTypes types, long blobLimit, long treeDepthLimit) {
		this.types = requireNonNull(types);
		this.blobLimit = blobLimit;
		this.treeDepthLimit = treeDepthLimit;
	}

	/**
	 * Process the content of "filter" line from the protocol. It has a shape
	 * like:
	 *
	 * <ul>
	 *   <li>"blob:none"
	 *   <li>"blob:limit=N", with N &gt;= 0
	 *   <li>"tree:DEPTH", with DEPTH &gt;= 0
	 * </ul>
	 *
	 * @param filterLine
	 *            the content of the "filter" line in the protocol
	 * @return a FilterSpec representing the given filter
	 * @throws PackProtocolException
	 *             invalid filter because due to unrecognized format or
	 *             negative/non-numeric filter.
	 */
	public static FilterSpec fromFilterLine(String filterLine)
			throws PackProtocolException {
		if (filterLine.equals("blob:none")) { //$NON-NLS-1$
			return FilterSpec.withObjectTypes(
					ObjectTypes.allow(OBJ_TREE, OBJ_COMMIT, OBJ_TAG));
		} else if (filterLine.startsWith("blob:limit=")) { //$NON-NLS-1$
			long blobLimit = -1;
			try {
				blobLimit = Long
						.parseLong(filterLine.substring("blob:limit=".length())); //$NON-NLS-1$
			} catch (NumberFormatException e) {
				// Do not change blobLimit so that we throw a
				// PackProtocolException later.
			}
			if (blobLimit >= 0) {
				return FilterSpec.withBlobLimit(blobLimit);
			}
		} else if (filterLine.startsWith("tree:")) { //$NON-NLS-1$
			long treeDepthLimit = -1;
			try {
				treeDepthLimit = Long
						.parseLong(filterLine.substring("tree:".length())); //$NON-NLS-1$
			} catch (NumberFormatException e) {
				// Do not change blobLimit so that we throw a
				// PackProtocolException later.
			}
			if (treeDepthLimit >= 0) {
				return FilterSpec.withTreeDepthLimit(treeDepthLimit);
			}
		}

		// Did not match any known filter format.
		throw new PackProtocolException(
				MessageFormat.format(JGitText.get().invalidFilter, filterLine));
	}

	/**
	 * Specify permitted object types
	 *
	 * @param types
	 *            set of permitted object types, for use in "blob:none" and
	 *            "object:none" filters
	 * @return a filter spec which restricts to objects of the specified types
	 */
	static FilterSpec withObjectTypes(ObjectTypes types) {
		return new FilterSpec(types, -1, -1);
	}

	/**
	 * Specify blob limit
	 *
	 * @param blobLimit
	 *            the blob limit in a "blob:[limit]" filter line
	 * @return a filter spec which filters blobs above a certain size
	 */
	static FilterSpec withBlobLimit(long blobLimit) {
		if (blobLimit < 0) {
			throw new IllegalArgumentException(
					"blobLimit cannot be negative: " + blobLimit); //$NON-NLS-1$
		}
		return new FilterSpec(ObjectTypes.ALL, blobLimit, -1);
	}

	/**
	 * Specify tree depth limit
	 *
	 * @param treeDepthLimit
	 *            the tree depth limit in a "tree:[depth]" filter line
	 * @return a filter spec which filters blobs and trees beyond a certain tree
	 *         depth
	 */
	static FilterSpec withTreeDepthLimit(long treeDepthLimit) {
		if (treeDepthLimit < 0) {
			throw new IllegalArgumentException(
					"treeDepthLimit cannot be negative: " + treeDepthLimit); //$NON-NLS-1$
		}
		return new FilterSpec(ObjectTypes.ALL, -1, treeDepthLimit);
	}

	/**
	 * A placeholder that indicates no filtering.
	 */
	public static final FilterSpec NO_FILTER = new FilterSpec(ObjectTypes.ALL, -1, -1);

	/**
	 * Whether object type is allowed
	 *
	 * @param type
	 *            a Git object type, such as
	 *            {@link org.eclipse.jgit.lib.Constants#OBJ_BLOB}
	 * @return whether this filter allows objects of the specified type
	 *
	 * @since 5.9
	 */
	public boolean allowsType(int type) {
		return types.contains(type);
	}

	/**
	 * Get blob size limit
	 *
	 * @return -1 if this filter does not filter blobs based on size, or a
	 *         non-negative integer representing the max size of blobs to allow
	 */
	public long getBlobLimit() {
		return blobLimit;
	}

	/**
	 * Get tree depth limit
	 *
	 * @return -1 if this filter does not filter blobs and trees based on depth,
	 *         or a non-negative integer representing the max tree depth of
	 *         blobs and trees to fetch
	 */
	public long getTreeDepthLimit() {
		return treeDepthLimit;
	}

	/**
	 * Whether this filter is a no-op
	 *
	 * @return true if this filter doesn't filter out anything
	 */
	public boolean isNoOp() {
		return types.equals(ObjectTypes.ALL) && blobLimit == -1 && treeDepthLimit == -1;
	}

	/**
	 * Get filter line describing this spec
	 *
	 * @return the filter line which describes this spec, e.g. "filter
	 *         blob:limit=42"
	 */
	@Nullable
	public String filterLine() {
		if (isNoOp()) {
			return null;
		} else if (types.equals(ObjectTypes.allow(OBJ_TREE, OBJ_COMMIT, OBJ_TAG)) &&
					blobLimit == -1 && treeDepthLimit == -1) {
			return OPTION_FILTER + " blob:none"; //$NON-NLS-1$
		} else if (types.equals(ObjectTypes.ALL) && blobLimit >= 0 && treeDepthLimit == -1) {
			return OPTION_FILTER + " blob:limit=" + blobLimit; //$NON-NLS-1$
		} else if (types.equals(ObjectTypes.ALL) && blobLimit == -1 && treeDepthLimit >= 0) {
			return OPTION_FILTER + " tree:" + treeDepthLimit; //$NON-NLS-1$
		} else {
			throw new IllegalStateException();
		}
	}
}
