/*******************************************************************************
 * Copyright (c) 2017 Google, Inc 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:
 *   Stefan Xenos (Google) - Initial implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core.nd.field;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jdt.internal.core.nd.ITypeFactory;
import org.eclipse.jdt.internal.core.nd.Nd;
import org.eclipse.jdt.internal.core.nd.db.Database;
import org.eclipse.jdt.internal.core.nd.db.ModificationLog;
import org.eclipse.jdt.internal.core.nd.db.ModificationLog.Tag;
import org.eclipse.jdt.internal.core.nd.util.MathUtils;

/**
 * Stores a singly-linked list of blocks, each of which contains a variable number of embedded elements.
 * Each block contains a header containing the size of the block and pointer to the next block, followed
 * by the embedded elements themselves.
 */
public class FieldList<T> extends BaseField implements IDestructableField {
	/**
	 * Pointer to the first block.
	 */
	public final static FieldPointer FIRST_BLOCK;
	/**
	 * Pointer to the block where insertions are currently happening. This is only null if there are no allocated
	 * blocks. If there are any blocks containing elements, this points to the last block with a nonzero number of
	 * elements.
	 */
	public final static FieldPointer LAST_BLOCK_WITH_ELEMENTS;

	@SuppressWarnings("rawtypes")
	private static final StructDef<FieldList> type;
	private static final int LIST_HEADER_BYTES;
	private static final long MAX_BYTES_IN_A_CHUNK = Database.getBytesThatFitInChunks(1);

	private final StructDef<T> elementType;
	private final int elementsPerBlock;
	private final StructDef<?> ownerType;
	private final Tag allocateTag;
	private final Tag appendTag;
	private final Tag destructTag;

	static {
		type = StructDef.createAbstract(FieldList.class);
		FIRST_BLOCK = type.addPointer();
		LAST_BLOCK_WITH_ELEMENTS = type.addPointer();

		type.done();
		LIST_HEADER_BYTES = MathUtils.roundUpToNearestMultipleOfPowerOfTwo(type.size(), Database.BLOCK_SIZE_DELTA);
	}

	private static class BlockHeader {
		// This points to the next block if there is one, or null if not.
		public final static FieldPointer NEXT_BLOCK;
		public final static FieldShort BLOCK_SIZE;
		public final static FieldShort ELEMENTS_IN_USE;
		public static final int BLOCK_HEADER_BYTES;

		@SuppressWarnings("hiding")
		private static final StructDef<BlockHeader> type;

		static {
			type = StructDef.createAbstract(BlockHeader.class);

			NEXT_BLOCK = type.addPointer();
			BLOCK_SIZE = type.addShort();
			ELEMENTS_IN_USE = type.addShort();
			type.done();

			BLOCK_HEADER_BYTES = MathUtils.roundUpToNearestMultipleOfPowerOfTwo(type.size(), Database.BLOCK_SIZE_DELTA);
		}
	}

	private FieldList(StructDef<?> ownerType, StructDef<T> elementType,  int elementsPerBlock) {
		this.elementType = elementType;
		this.elementsPerBlock = elementsPerBlock;
		this.ownerType = ownerType;
		int fieldNumber = ownerType.getNumFields();
		setFieldName("field " + fieldNumber + ", a " + getClass().getSimpleName() //$NON-NLS-1$//$NON-NLS-2$
				+ " in struct " + ownerType.getStructName());//$NON-NLS-1$
		this.allocateTag = ModificationLog.createTag("Allocating elements for " + getFieldName()); //$NON-NLS-1$
		this.appendTag = ModificationLog.createTag("Appending to " + getFieldName()); //$NON-NLS-1$
		this.destructTag = ModificationLog.createTag("Deallocating " + getFieldName()); //$NON-NLS-1$
	}

	/**
	 * Creates a new {@link FieldList} in the given struct which contains elements of the given type. The resulting list
	 * will grow by 1 element each time it overflows.
	 *
	 * @param ownerStruct
	 *            the struct to which the new list field will be added. Must not have had {@link StructDef#done()}
	 *            invoked on it yet.
	 * @param elementType
	 *            the type of elements that will be contained in the struct.
	 * @return a newly-constructed list field in the given struct.
	 */
	public static <T> FieldList<T> create(StructDef<?> ownerStruct, StructDef<T> elementType) {
		return create(ownerStruct, elementType, 1);
	}

	/**
	 * Creates a new {@link FieldList} in the given struct which contains elements of the given type. The resulting list
	 * will grow by the given number of elements each time it overflows.
	 *
	 * @param ownerStruct
	 *            the struct to which the new list field will be added. Must not have had {@link StructDef#done()}
	 *            invoked on it yet.
	 * @param elementType
	 *            the type of elements that will be contained in the struct.
	 * @param elementsPerBlock
	 *            the number of elements that will be allocated each time the list overflows.
	 * @return a newly-constructed list field in the given struct.
	 */
	public static <T> FieldList<T> create(StructDef<?> ownerStruct, StructDef<T> elementType, int elementsPerBlock) {
		FieldList<T> result = new FieldList<>(ownerStruct, elementType, elementsPerBlock);
		ownerStruct.add(result);
		ownerStruct.addDestructableField(result);
		return result;
	}

	private int getElementSize() {
		int recordSize = this.elementType.getFactory().getRecordSize();
		return MathUtils.roundUpToNearestMultipleOfPowerOfTwo(recordSize, Database.BLOCK_SIZE_DELTA);
	}

	@Override
	public int getRecordSize() {
		return LIST_HEADER_BYTES;
	}

	/**
	 * Returns the contents of the receiver as a {@link List}.
	 *
	 * @param nd the database to be queried.
	 * @param address the address of the parent struct
	 */
	public List<T> asList(Nd nd, long address) {
		long headerStartAddress = address + this.offset;
		long firstBlockAddress = FIRST_BLOCK.get(nd, headerStartAddress);

		List<T> result = new ArrayList<>();

		long nextBlockAddress = firstBlockAddress;
		while (nextBlockAddress != 0) {
			long currentBlockAddress = nextBlockAddress;
			nextBlockAddress = BlockHeader.NEXT_BLOCK.get(nd, currentBlockAddress);
			int elementsInBlock = BlockHeader.ELEMENTS_IN_USE.get(nd, currentBlockAddress);
			long firstElementInBlockAddress = currentBlockAddress + BlockHeader.BLOCK_HEADER_BYTES;

			readElements(result, nd, firstElementInBlockAddress, elementsInBlock);
		}

		return result;
	}

	private void readElements(List<T> result, Nd nd, long nextElementAddress, int count) {
		ITypeFactory<T> factory = this.elementType.getFactory();

		int size = getElementSize();
		for (; count > 0; count--) {
			result.add(factory.create(nd, nextElementAddress));
			nextElementAddress += size;
		}
	}

	public T append(Nd nd, long address) {
		Database db = nd.getDB();
		db.getLog().start(this.appendTag);
		try {
			long headerStartAddress = address + this.offset;
			long nextBlockAddress = LAST_BLOCK_WITH_ELEMENTS.get(nd, headerStartAddress);

			// Ensure that there's at least one block
			long insertionBlockAddress = nextBlockAddress;
			if (nextBlockAddress == 0) {
				long newBlockAddress = allocateNewBlock(nd, this.elementsPerBlock);
				LAST_BLOCK_WITH_ELEMENTS.put(nd, headerStartAddress, newBlockAddress);
				FIRST_BLOCK.put(nd, headerStartAddress, newBlockAddress);
				insertionBlockAddress = newBlockAddress;
			}

			// Check if there's any free space in this block
			int elementsInBlock = BlockHeader.ELEMENTS_IN_USE.get(nd, insertionBlockAddress);
			int blockSize = BlockHeader.BLOCK_SIZE.get(nd, insertionBlockAddress);

			if (elementsInBlock >= blockSize) {
				long nextBlock = BlockHeader.NEXT_BLOCK.get(nd, insertionBlockAddress);
				if (nextBlock == 0) {
					nextBlock = allocateNewBlock(nd, this.elementsPerBlock);
					BlockHeader.NEXT_BLOCK.put(nd, insertionBlockAddress, nextBlock);
				}
				LAST_BLOCK_WITH_ELEMENTS.put(nd, headerStartAddress, nextBlock);
				insertionBlockAddress = nextBlock;
				elementsInBlock = BlockHeader.ELEMENTS_IN_USE.get(nd, insertionBlockAddress);
			}

			BlockHeader.ELEMENTS_IN_USE.put(nd, insertionBlockAddress, (short) (elementsInBlock + 1));
			int elementSize = getElementSize();

			long resultAddress = insertionBlockAddress + BlockHeader.BLOCK_HEADER_BYTES + elementsInBlock * elementSize;
			assert ((resultAddress - Database.BLOCK_HEADER_SIZE) & (Database.BLOCK_SIZE_DELTA - 1)) == 0;
			return this.elementType.getFactory().create(nd, resultAddress);
		} finally {
			db.getLog().end(this.appendTag);
		}
	}

	/**
	 * Ensures that the receiver will have space for the given number of elements without additional
	 * allocation. Callers should invoke this prior to a sequence of {@link FieldList#append(Nd, long)}
	 * calls if they know in advance how many elements will be appended. Will create the minimum number
	 * of extra blocks needed to the given number of additional elements.
	 */
	public void allocate(Nd nd, long address, int numElements) {
		Database db = nd.getDB();
		db.getLog().start(this.allocateTag);
		try {
			if (numElements == 0) {
				// Not an error, but there's nothing to do if the caller didn't actually ask for anything to be allocated.
				return;
			}
			long headerStartAddress = address + this.offset;
			long nextBlockAddress = LAST_BLOCK_WITH_ELEMENTS.get(nd, headerStartAddress);

			int maxBlockSizeThatFitsInAChunk = (int) ((MAX_BYTES_IN_A_CHUNK - BlockHeader.BLOCK_HEADER_BYTES)
					/ getElementSize());

			// Ensure that there's at least one block
			if (nextBlockAddress == 0) {
				int firstAllocation = Math.min(numElements, maxBlockSizeThatFitsInAChunk);
				nextBlockAddress = allocateNewBlock(nd, firstAllocation);
				LAST_BLOCK_WITH_ELEMENTS.put(nd, headerStartAddress, nextBlockAddress);
				FIRST_BLOCK.put(nd, headerStartAddress, nextBlockAddress);
			}

			// Check if there's any free space in this block
			int remainingToAllocate = numElements;
			while (true) {
				long currentBlockAddress = nextBlockAddress;
				nextBlockAddress = BlockHeader.NEXT_BLOCK.get(nd, currentBlockAddress);
				int elementsInUse = BlockHeader.ELEMENTS_IN_USE.get(nd, currentBlockAddress);
				int blockSize = BlockHeader.BLOCK_SIZE.get(nd, currentBlockAddress);

				remainingToAllocate -= (blockSize - elementsInUse);
				if (remainingToAllocate <= 0) {
					break;
				}

				if (nextBlockAddress == 0) {
					nextBlockAddress = allocateNewBlock(nd, Math.min(maxBlockSizeThatFitsInAChunk, numElements));
					BlockHeader.NEXT_BLOCK.put(nd, currentBlockAddress, nextBlockAddress);
				}
			}
		} finally {
			db.getLog().end(this.allocateTag);
		}
	}

	private long allocateNewBlock(Nd nd, int blockSize) {
		short poolId = getMemoryPoolId(nd);
		int elementSize = getElementSize();
		long bytesNeeded = BlockHeader.BLOCK_HEADER_BYTES + blockSize * elementSize;
		// If we're close enough to filling the chunk that we wouldn't be able to fit any more elements anyway, allocate
		// the entire chunk. Although it wastes a small amount of space, it ensures that the blocks can be more easily
		// reused rather than being fragmented. It also allows freed blocks to be merged via the large block allocator.
		if (MAX_BYTES_IN_A_CHUNK - bytesNeeded < elementSize) {
			bytesNeeded = MAX_BYTES_IN_A_CHUNK;
		}
		long result = nd.getDB().malloc(bytesNeeded, poolId);
		BlockHeader.BLOCK_SIZE.put(nd, result, (short) blockSize);
		return result;
	}

	private short getMemoryPoolId(Nd nd) {
		short poolId = Database.POOL_LINKED_LIST;
		if (this.ownerType != null) {
			Class<?> structClass = this.ownerType.getStructClass();
			if (nd.getTypeRegistry().isRegisteredClass(structClass)) {
				poolId = (short) (Database.POOL_FIRST_NODE_TYPE + nd.getNodeType(structClass));
			}
		}
		return poolId;
	}

	@Override
	public void destruct(Nd nd, long address) {
		Database db = nd.getDB();
		db.getLog().start(this.destructTag);
		try {
			short poolId = getMemoryPoolId(nd);
			long headerStartAddress = address + this.offset;
			long firstBlockAddress = FIRST_BLOCK.get(nd, headerStartAddress);

			long nextBlockAddress = firstBlockAddress;
			while (nextBlockAddress != 0) {
				long currentBlockAddress = nextBlockAddress;
				nextBlockAddress = BlockHeader.NEXT_BLOCK.get(nd, currentBlockAddress);
				int elementsInBlock = BlockHeader.ELEMENTS_IN_USE.get(nd, currentBlockAddress);
				destructElements(nd, currentBlockAddress + BlockHeader.BLOCK_HEADER_BYTES, elementsInBlock);
				db.free(currentBlockAddress, poolId);
			}

			db.clearRange(headerStartAddress, getRecordSize());
		} finally {
			db.getLog().end(this.destructTag);
		}
	}

	private void destructElements(Nd nd, long nextElementAddress, int count) {
		ITypeFactory<T> factory = this.elementType.getFactory();

		int size = getElementSize();
		while (--count >= 0) {
			factory.destruct(nd, nextElementAddress);
			nextElementAddress += size;
		}
	}
}
