/*
 * Copyright (C) 2012, Google Inc. 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.lib;

import java.util.Iterator;

import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;

import com.googlecode.javaewah.EWAHCompressedBitmap;

/**
 * A compressed bitmap representation of the entire object graph.
 *
 * @since 3.0
 */
public interface BitmapIndex {
	/**
	 * Get the bitmap for the id. The returned bitmap is immutable and the
	 * bitwise operations return the result of the operation in a new Bitmap.
	 *
	 * @param objectId
	 *            the object ID
	 * @return the Bitmap for the objectId or null, if one does not exist.
	 */
	Bitmap getBitmap(AnyObjectId objectId);

	/**
	 * Create a new {@code BitmapBuilder} based on the values in the index.
	 *
	 * @return a new {@code BitmapBuilder} based on the values in the index.
	 */
	BitmapBuilder newBitmapBuilder();

	/**
	 * Report the results of {@link #getBitmap(AnyObjectId)}
	 *
	 * @since 6.8
	 */
	interface BitmapLookupListener {

		/**
		 * This object has a bitmap in the index
		 *
		 * @param oid
		 *            object id
		 */
		void onBitmapFound(AnyObjectId oid);

		/**
		 * This object does not have a bitmap in the index
		 *
		 * @param oid
		 *            object id
		 */
		void onBitmapNotFound(AnyObjectId oid);

		/**
		 * No-op instance
		 */
		BitmapLookupListener NOOP = new BitmapLookupListener() {
			@Override
			public void onBitmapFound(AnyObjectId oid) {
				// Nothing to do
			}

			@Override
			public void onBitmapNotFound(AnyObjectId oid) {
				// Nothing to do
			}
		};
	}

	/**
	 * Report to this listener whether {@link #getBitmap(AnyObjectId)} finds a
	 * commit.
	 *
	 * @param listener
	 *            instance listening to lookup events in the index. Never null.
	 *            Set to {@link BitmapLookupListener#NOOP} to disable.
	 * @since 6.8
	 */
	default void addBitmapLookupListener(BitmapLookupListener listener) {
		// Empty implementation for API compatibility
	}

	/**
	 * A bitmap representation of ObjectIds that can be iterated to return the
	 * underlying {@code ObjectId}s or operated on with other {@code Bitmap}s.
	 */
	public interface Bitmap extends Iterable<BitmapObject> {
		/**
		 * Bitwise-OR the current bitmap with the value from the other
		 * bitmap.
		 *
		 * @param other
		 *            the other bitmap
		 * @return a bitmap that is the bitwise-OR.
		 */
		Bitmap or(Bitmap other);

		/**
		 * Bitwise-AND-NOT the current bitmap with the value from the other
		 * bitmap.
		 *
		 * @param other
		 *            the other bitmap
		 * @return a bitmap that is the bitwise-AND-NOT.
		 */
		Bitmap andNot(Bitmap other);

		/**
		 * Bitwise-XOR the current bitmap with the value from the other
		 * bitmap.
		 *
		 * @param other
		 *            the other bitmap
		 * @return a bitmap that is the bitwise-XOR.
		 */
		Bitmap xor(Bitmap other);

		/**
		 * Returns an iterator over a set of elements of type BitmapObject. The
		 * BitmapObject instance is reused across calls to
		 * {@link Iterator#next()} for performance reasons.
		 *
		 * @return an Iterator.
		 */
		@Override
		Iterator<BitmapObject> iterator();

		/**
		 * Returns the corresponding raw compressed EWAH bitmap of the bitmap.
		 *
		 * @return the corresponding {@code EWAHCompressedBitmap}
		 * @since 5.8
		 */
		EWAHCompressedBitmap retrieveCompressed();
	}

	/**
	 * A builder for a bitmap. The bitwise operations update the builder and
	 * return a reference to the current builder.
	 */
	public interface BitmapBuilder extends Bitmap {

		/**
		 * Whether the bitmap has the id set.
		 *
		 * @param objectId
		 *            the object ID
		 * @return whether the bitmap currently contains the object ID
		 */
		boolean contains(AnyObjectId objectId);

		/**
		 * Adds the id to the bitmap.
		 *
		 * @param objectId
		 *            the object ID
		 * @param type
		 *            the Git object type. See {@link Constants}.
		 * @return the current builder.
		 * @since 4.2
		 */
		BitmapBuilder addObject(AnyObjectId objectId, int type);

		/**
		 * Remove the id from the bitmap.
		 *
		 * @param objectId
		 *            the object ID
		 */
		void remove(AnyObjectId objectId);

		/**
		 * Bitwise-OR the current bitmap with the value from the other bitmap.
		 *
		 * @param other
		 *            the other bitmap
		 * @return the current builder.
		 */
		@Override
		BitmapBuilder or(Bitmap other);

		/**
		 * Bitwise-AND-NOT the current bitmap with the value from the other
		 * bitmap.
		 *
		 * @param other
		 *            the other bitmap
		 * @return the current builder.
		 */
		@Override
		BitmapBuilder andNot(Bitmap other);

		/**
		 * Bitwise-XOR the current bitmap with the value from the other bitmap.
		 *
		 * @param other
		 *            the other bitmap
		 * @return the current builder.
		 */
		@Override
		BitmapBuilder xor(Bitmap other);

		/**
		 * Build the bitmap
		 *
		 * @return the fully built immutable bitmap
		 */
		Bitmap build();

		/**
		 * Determines if the entire bitmap index is contained in the bitmap. If
		 * it is, the matching bits are removed from the bitmap and true is
		 * returned. If the bitmap index is null, false is returned.
		 *
		 * @param bitmapIndex
		 *            the bitmap index to check if it is completely contained
		 *            inside of the current bitmap.
		 * @return {@code true} if the bitmap index was a complete match.
		 */
		boolean removeAllOrNone(PackBitmapIndex bitmapIndex);

		/**
		 * Get number of elements in the bitmap
		 *
		 * @return the number of elements in the bitmap.
		 */
		int cardinality();

		/**
		 * Get the BitmapIndex for this BitmapBuilder.
		 *
		 * @return the BitmapIndex for this BitmapBuilder
		 *
		 * @since 4.2
		 */
		BitmapIndex getBitmapIndex();
	}
}
