/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.parser;

/**
 * Internal field structure for parsing recovery
 */
import java.util.HashSet;
import java.util.Set;

import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;

public class RecoveredUnit extends RecoveredElement {

	public CompilationUnitDeclaration unitDeclaration;

	public RecoveredImport[] imports;
	public int importCount;
	public RecoveredModule module;
	public RecoveredType[] types;
	public int typeCount;

	int pendingModifiers;
	int pendingModifersSourceStart = -1;
	RecoveredAnnotation[] pendingAnnotations;
	int pendingAnnotationCount;

public RecoveredUnit(CompilationUnitDeclaration unitDeclaration, int bracketBalance, Parser parser){
	super(null, bracketBalance, parser);
	this.unitDeclaration = unitDeclaration;
}
@Override
public RecoveredElement addAnnotationName(int identifierPtr, int identifierLengthPtr, int annotationStart, int bracketBalanceValue) {
	if (this.pendingAnnotations == null) {
		this.pendingAnnotations = new RecoveredAnnotation[5];
		this.pendingAnnotationCount = 0;
	} else {
		if (this.pendingAnnotationCount == this.pendingAnnotations.length) {
			System.arraycopy(
				this.pendingAnnotations,
				0,
				(this.pendingAnnotations = new RecoveredAnnotation[2 * this.pendingAnnotationCount]),
				0,
				this.pendingAnnotationCount);
		}
	}

	RecoveredAnnotation element = new RecoveredAnnotation(identifierPtr, identifierLengthPtr, annotationStart, this, bracketBalanceValue);

	this.pendingAnnotations[this.pendingAnnotationCount++] = element;

	return element;
}
@Override
public void addModifier(int flag, int modifiersSourceStart) {
	this.pendingModifiers |= flag;

	if (this.pendingModifersSourceStart < 0) {
		this.pendingModifersSourceStart = modifiersSourceStart;
	}
}
/*
 *	Record a method declaration: should be attached to last type
 */
@Override
public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {

	/* attach it to last type - if any */
	if (this.typeCount > 0){
		RecoveredType type = this.types[this.typeCount -1];
		int start = type.bodyEnd;
		int end = type.typeDeclaration.bodyEnd;
		type.bodyEnd = 0; // reset position
		type.typeDeclaration.declarationSourceEnd = 0; // reset position
		type.typeDeclaration.bodyEnd = 0;

		int kind = TypeDeclaration.kind(type.typeDeclaration.modifiers);
		if(start > 0 &&
				start < end &&
				kind != TypeDeclaration.INTERFACE_DECL &&
				kind != TypeDeclaration.ANNOTATION_TYPE_DECL) {
			// the } of the last type can be considered as the end of an initializer
			Block block = new Block(0);
			block.sourceStart = block.sourceEnd = end;
			Initializer initializer = new Initializer(block, 0);
			initializer.bodyStart = end;
			initializer.bodyEnd = end;
			initializer.declarationSourceStart = end;
			initializer.declarationSourceEnd = end;
			initializer.sourceStart = end;
			initializer.sourceEnd = end;
			type.add(initializer, bracketBalanceValue);
		}

		resetPendingModifiers();

		return type.add(methodDeclaration, bracketBalanceValue);
	}
	return this; // ignore
}
/*
 *	Record a field declaration: should be attached to last type
 */
@Override
public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {

	/* attach it to last type - if any */
	if (this.typeCount > 0){
		RecoveredType type = this.types[this.typeCount -1];
		type.bodyEnd = 0; // reset position
		type.typeDeclaration.declarationSourceEnd = 0; // reset position
		type.typeDeclaration.bodyEnd = 0;

		resetPendingModifiers();

		return type.add(fieldDeclaration, bracketBalanceValue);
	}
	return this; // ignore
}
public RecoveredElement add(ExportsStatement exportReference, int bracketBalanceValue) {
	return this.module != null ? this.module.add(exportReference, bracketBalanceValue) : null;
}

@Override
public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) {
	resetPendingModifiers();

	if (this.imports == null) {
		this.imports = new RecoveredImport[5];
		this.importCount = 0;
	} else {
		if (this.importCount == this.imports.length) {
			System.arraycopy(
				this.imports,
				0,
				(this.imports = new RecoveredImport[2 * this.importCount]),
				0,
				this.importCount);
		}
	}
	RecoveredImport element = new RecoveredImport(importReference, this, bracketBalanceValue);
	this.imports[this.importCount++] = element;

	/* if import not finished, then import becomes current */
	if (importReference.declarationSourceEnd == 0) return element;
	return this;
}
@Override
public RecoveredElement add(ModuleDeclaration moduleDeclaration, int bracketBalanceValue){
	this.module = new RecoveredModule(moduleDeclaration, this, bracketBalanceValue);
	return this.module;
}
@Override
public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
	
	if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0){
		if (this.typeCount > 0) {
			// add it to the last type
			RecoveredType lastType = this.types[this.typeCount-1];
			lastType.bodyEnd = 0; // reopen type
			lastType.typeDeclaration.bodyEnd = 0; // reopen type
			lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type
			lastType.bracketBalance++; // expect one closing brace

			resetPendingModifiers();

			return lastType.add(typeDeclaration, bracketBalanceValue);
		}
	}
	if (this.types == null) {
		this.types = new RecoveredType[5];
		this.typeCount = 0;
	} else {
		if (this.typeCount == this.types.length) {
			System.arraycopy(
				this.types,
				0,
				(this.types = new RecoveredType[2 * this.typeCount]),
				0,
				this.typeCount);
		}
	}
	RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
	this.types[this.typeCount++] = element;

	if(this.pendingAnnotationCount > 0) {
		element.attach(
				this.pendingAnnotations,
				this.pendingAnnotationCount,
				this.pendingModifiers,
				this.pendingModifersSourceStart);
	}
	resetPendingModifiers();

	/* if type not finished, then type becomes current */
	if (typeDeclaration.declarationSourceEnd == 0) return element;
	return this;
}
/*
 * Answer the associated parsed structure
 */
@Override
public ASTNode parseTree(){
	return this.unitDeclaration;
}
@Override
public void resetPendingModifiers() {
	this.pendingAnnotations = null;
	this.pendingAnnotationCount = 0;
	this.pendingModifiers = 0;
	this.pendingModifersSourceStart = -1;
}
/*
 * Answer the very source end of the corresponding parse node
 */
@Override
public int sourceEnd(){
	return this.unitDeclaration.sourceEnd;
}
@Override
public int getLastStart() {
	int lastTypeStart = -1;

	if (this.typeCount > 0) {
		TypeDeclaration lastType = this.types[this.typeCount - 1].typeDeclaration;
		if (lastTypeStart < lastType.declarationSourceStart && lastType.declarationSourceStart != 0) {
			lastTypeStart = lastType.declarationSourceStart;
		}
	}
	return lastTypeStart;
}
@Override
public String toString(int tab) {
	StringBuffer result = new StringBuffer(tabString(tab));
	result.append("Recovered unit: [\n"); //$NON-NLS-1$
	this.unitDeclaration.print(tab + 1, result);
	result.append(tabString(tab + 1));
	result.append("]"); //$NON-NLS-1$
	if (this.imports != null) {
		for (int i = 0; i < this.importCount; i++) {
			result.append("\n"); //$NON-NLS-1$
			result.append(this.imports[i].toString(tab + 1));
		}
	}
	if (this.types != null) {
		for (int i = 0; i < this.typeCount; i++) {
			result.append("\n"); //$NON-NLS-1$
			result.append(this.types[i].toString(tab + 1));
		}
	}
	return result.toString();
}
public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){

	/* update imports */
	if (this.importCount > 0){
		ImportReference[] importRefences = new ImportReference[this.importCount];
		for (int i = 0; i < this.importCount; i++){
			importRefences[i] = this.imports[i].updatedImportReference();
		}
		this.unitDeclaration.imports = importRefences;
	}
	if (this.module != null) {
		this.unitDeclaration.moduleDeclaration = this.module.updatedModuleDeclaration();
	}
	/* update types */
	if (this.typeCount > 0){
		int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length;
		TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + this.typeCount];
		if (existingCount > 0){
			System.arraycopy(this.unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
		}
		// may need to update the declarationSourceEnd of the last type
		if (this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
			this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd = this.unitDeclaration.sourceEnd;
			this.types[this.typeCount - 1].typeDeclaration.bodyEnd = this.unitDeclaration.sourceEnd;
		}
		
		Set<TypeDeclaration> knownTypes = new HashSet<>();
		int actualCount = existingCount;
		for (int i = 0; i < this.typeCount; i++){
			TypeDeclaration typeDecl = this.types[i].updatedTypeDeclaration(0, knownTypes);
			// filter out local types (12454)
			if (typeDecl != null && (typeDecl.bits & ASTNode.IsLocalType) == 0){
				typeDeclarations[actualCount++] = typeDecl;
			}
		}
		if (actualCount != this.typeCount){
			System.arraycopy(
				typeDeclarations,
				0,
				typeDeclarations = new TypeDeclaration[existingCount+actualCount],
				0,
				existingCount+actualCount);
		}
		this.unitDeclaration.types = typeDeclarations;
	}
	return this.unitDeclaration;
}
@Override
public void updateParseTree(){
	updatedCompilationUnitDeclaration();
}
/*
 * Update the sourceEnd of the corresponding parse node
 */
@Override
public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
	if (this.unitDeclaration.sourceEnd == 0)
		this.unitDeclaration.sourceEnd = bodyEnd;
}
}
