/*******************************************************************************
 * Copyright (c) 2015, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * This is an implementation of an early-draft specification developed under the Java
 * Community Process (JCP) and is made available for testing and evaluation purposes
 * only. The code is not compatible with any specification of the JCP.
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceModuleBinding;
import org.eclipse.jdt.internal.compiler.lookup.SplitPackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.problem.AbortType;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;

public class ModuleDeclaration extends ASTNode {

	public ExportsStatement[] exports;
	public RequiresStatement[] requires;
	public UsesStatement[] uses;
	public ProvidesStatement[] services;
	public OpensStatement[] opens;
	public Annotation[] annotations;
	public int exportsCount;
	public int requiresCount;
	public int usesCount;
	public int servicesCount;
	public int opensCount;
	public SourceModuleBinding binding;
	public int declarationSourceStart;
	public int declarationSourceEnd;
	public int bodyStart;
	public int bodyEnd; // doesn't include the trailing comment if any.
	public int modifiersSourceStart;
	BlockScope scope;
	public char[][] tokens;
	public char[] moduleName;
	public long[] sourcePositions;
	public int modifiers = ClassFileConstants.AccDefault;
	boolean ignoreFurtherInvestigation;
	boolean hasResolvedModuleDirectives;
	boolean hasResolvedPackageDirectives;
	CompilationResult compilationResult;

	public ModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions) {
		this.compilationResult = compilationResult;
		this.exportsCount = 0;
		this.requiresCount = 0;
		this.tokens = tokens;
		this.moduleName = CharOperation.concatWith(tokens, '.');
		this.sourcePositions = positions;
		this.sourceEnd = (int) (positions[positions.length-1] & 0x00000000FFFFFFFF);
		this.sourceStart = (int) (positions[0] >>> 32);
	}

	public ModuleBinding setBinding(SourceModuleBinding sourceModuleBinding) {
		this.binding = sourceModuleBinding;
		return sourceModuleBinding;
	}

	public void checkAndSetModifiers() {
		int realModifiers = this.modifiers & ExtraCompilerModifiers.AccJustFlag;
		int expectedModifiers = ClassFileConstants.ACC_OPEN | ClassFileConstants.ACC_SYNTHETIC;
		if ((realModifiers & ~(expectedModifiers)) != 0) {
			this.scope.problemReporter().illegalModifierForModule(this);
			realModifiers &= expectedModifiers;
		}
		int effectiveModifiers = ClassFileConstants.AccModule | realModifiers;
		this.modifiers = this.binding.modifiers = effectiveModifiers;
	}

	public boolean isOpen() {
		return (this.modifiers & ClassFileConstants.ACC_OPEN) != 0;
	}

	public void createScope(final Scope parentScope) {
		this.scope = new MethodScope(parentScope, null, true) {
			@Override
			public ProblemReporter problemReporter() {
				// this method scope has no reference context so we better deletegate to the 'real' cuScope:
				return parentScope.problemReporter();
			}
		};
	}

	public void generateCode() {
		if ((this.bits & ASTNode.HasBeenGenerated) != 0)
			return;
		this.bits |= ASTNode.HasBeenGenerated;
		if (this.ignoreFurtherInvestigation) {
			return;
		}
		try {
			// create the result for a compiled type
			LookupEnvironment env = this.scope.environment();
			ClassFile classFile = env.classFilePool.acquireForModule(this.binding, env.globalOptions);
			classFile.initializeForModule(this.binding);

			// finalize the compiled type result
			classFile.addModuleAttributes(this.binding, this.annotations, this.scope.referenceCompilationUnit());
			this.scope.referenceCompilationUnit().compilationResult.record(
				this.binding.moduleName,
				classFile);
		} catch (AbortType e) {
			if (this.binding == null)
				return;
		}
	}

	/** Resolve those module directives that relate to modules (requires). */
	public void resolveModuleDirectives(CompilationUnitScope cuScope) {
		if (this.binding == null) {
			this.ignoreFurtherInvestigation = true;
			return;
		}
		if (this.hasResolvedModuleDirectives)
			return;

		this.hasResolvedModuleDirectives = true;

		Set<ModuleBinding> requiredModules = new HashSet<ModuleBinding>();
		Set<ModuleBinding> requiredTransitiveModules = new HashSet<ModuleBinding>();
		for(int i = 0; i < this.requiresCount; i++) {
			RequiresStatement ref = this.requires[i];
			if (ref != null && ref.resolve(cuScope) != null) {
				if (!requiredModules.add(ref.resolvedBinding)) {
					cuScope.problemReporter().duplicateModuleReference(IProblem.DuplicateRequires, ref.module);
				}
				if (ref.isTransitive())
					requiredTransitiveModules.add(ref.resolvedBinding);
				Collection<ModuleBinding> deps = ref.resolvedBinding.dependencyGraphCollector().get();
				if (deps.contains(this.binding)) {
					cuScope.problemReporter().cyclicModuleDependency(this.binding, ref.module);
					requiredModules.remove(ref.module.binding);
				}
			}
		}
		this.binding.setRequires(requiredModules.toArray(new ModuleBinding[requiredModules.size()]),
								 requiredTransitiveModules.toArray(new ModuleBinding[requiredTransitiveModules.size()]));
	}

	/** Resolve those module directives that relate to packages (exports, opens). */
	public void resolvePackageDirectives(CompilationUnitScope cuScope) {
		if (this.binding == null) {
			this.ignoreFurtherInvestigation = true;
			return;
		}
		if (this.hasResolvedPackageDirectives)
			return;

		this.hasResolvedPackageDirectives = true;

		Set<PackageBinding> exportedPkgs = new HashSet<>();
		for (int i = 0; i < this.exportsCount; i++) {
			ExportsStatement ref = this.exports[i];
 			if (ref != null && ref.resolve(cuScope)) {
				if (!exportedPkgs.add(ref.resolvedPackage)) {
					cuScope.problemReporter().invalidPackageReference(IProblem.DuplicateExports, ref);
				}
				char[][] targets = null;
				if (ref.targets != null) {
					targets = new char[ref.targets.length][];
					for (int j = 0; j < targets.length; j++)
						targets[j] = ref.targets[j].moduleName;
				}
				this.binding.addResolvedExport(ref.resolvedPackage, targets);
			}
		}

		HashtableOfObject openedPkgs = new HashtableOfObject();
		for (int i = 0; i < this.opensCount; i++) {
			OpensStatement ref = this.opens[i];
			if (isOpen()) {
				cuScope.problemReporter().invalidOpensStatement(ref, this);
			} else {
				if (openedPkgs.containsKey(ref.pkgName)) {
					cuScope.problemReporter().invalidPackageReference(IProblem.DuplicateOpens, ref);
				} else {
					openedPkgs.put(ref.pkgName, ref);
					ref.resolve(cuScope);
				}
				char[][] targets = null;
				if (ref.targets != null) {
					targets = new char[ref.targets.length][];
					for (int j = 0; j < targets.length; j++)
						targets[j] = ref.targets[j].moduleName;
				}
				this.binding.addResolvedOpens(ref.resolvedPackage, targets);
			}
		}
	}

	/** Resolve those module directives that relate to types (provides / uses). */
	public void resolveTypeDirectives(CompilationUnitScope cuScope) {
		if (this.binding == null) {
			this.ignoreFurtherInvestigation = true;
			return;
		}
		ASTNode.resolveAnnotations(this.scope, this.annotations, this.binding);

		Set<TypeBinding> allTypes = new HashSet<TypeBinding>();
		for(int i = 0; i < this.usesCount; i++) {
			TypeBinding serviceBinding = this.uses[i].serviceInterface.resolveType(this.scope);
			if (serviceBinding != null && serviceBinding.isValidBinding()) {
				if (!(serviceBinding.isClass() || serviceBinding.isInterface() || serviceBinding.isAnnotationType())) {
					cuScope.problemReporter().invalidServiceRef(IProblem.InvalidServiceIntfType, this.uses[i].serviceInterface);
				}
				if (!allTypes.add(this.uses[i].serviceInterface.resolvedType)) {
					cuScope.problemReporter().duplicateTypeReference(IProblem.DuplicateUses, this.uses[i].serviceInterface);
				}
			}
		}
		this.binding.setUses(allTypes.toArray(new TypeBinding[allTypes.size()]));
		
		Set<TypeBinding> interfaces = new HashSet<>();
		for(int i = 0; i < this.servicesCount; i++) {
			this.services[i].resolve(this.scope);
			TypeBinding infBinding = this.services[i].serviceInterface.resolvedType;
			if (infBinding != null && infBinding.isValidBinding()) {
				if (!interfaces.add(this.services[i].serviceInterface.resolvedType)) { 
					cuScope.problemReporter().duplicateTypeReference(IProblem.DuplicateServices,
							this.services[i].serviceInterface);
				}
				this.binding.setImplementations(infBinding, this.services[i].getResolvedImplementations());
			}
		}
		this.binding.setServices(interfaces.toArray(new TypeBinding[interfaces.size()]));
	}

	public void analyseCode(CompilationUnitScope skope) {
		analyseModuleGraph(skope);
		analyseExportedPackages(skope);
	}
	
	private void analyseExportedPackages(CompilationUnitScope skope) {
		if (this.exports != null) {
			for (ExportsStatement export : this.exports) {
				PackageBinding pb = export.resolvedPackage;
				if (pb == null)
					continue;
				if (pb instanceof SplitPackageBinding)
					pb = ((SplitPackageBinding) pb).getIncarnation(this.binding);
				if (pb.hasCompilationUnit(true))
					continue;
				skope.problemReporter().invalidPackageReference(IProblem.PackageDoesNotExistOrIsEmpty, export);
			}
		}
	}
	public void analyseModuleGraph(CompilationUnitScope skope) {
		if (this.requires != null) {
			// collect transitively:
			Map<String, Set<ModuleBinding>> pack2mods = new HashMap<>();
			for (ModuleBinding requiredModule : this.binding.getAllRequiredModules()) {
				for (PackageBinding exportedPackage : requiredModule.getExports()) {
					if (this.binding.canAccess(exportedPackage)) {
						String packName = String.valueOf(exportedPackage.readableName());
						Set<ModuleBinding> mods = pack2mods.get(packName);
						if (mods == null)
							pack2mods.put(packName, mods = new HashSet<>());
						mods.add(requiredModule);
					}
				}
			}
			// report against the causing requires directives:
			for (RequiresStatement requiresStat : this.requires) {
				ModuleBinding requiredModule = requiresStat.resolvedBinding;
				if (requiredModule != null) {
					analyseOneDependency(requiresStat, requiredModule, skope, pack2mods);
					if (requiresStat.isTransitive()) {
						for (ModuleBinding secondLevelModule : requiredModule.getAllRequiredModules())
							analyseOneDependency(requiresStat, secondLevelModule, skope, pack2mods);
					}
				}
			}
		}
	}

	private void analyseOneDependency(RequiresStatement requiresStat, ModuleBinding requiredModule, CompilationUnitScope skope,
			Map<String, Set<ModuleBinding>> pack2mods)
	{
		for (PackageBinding pack : requiredModule.getExports()) {
			Set<ModuleBinding> mods = pack2mods.get(String.valueOf(pack.readableName()));
			if (mods != null && mods.size() > 1)
				skope.problemReporter().conflictingPackagesFromModules(pack, mods, requiresStat.sourceStart, requiresStat.sourceEnd);
		}
	}

	public StringBuffer printHeader(int indent, StringBuffer output) {
		if (this.annotations != null) {
			for (int i = 0; i < this.annotations.length; i++) {
				this.annotations[i].print(indent, output);
				if (i != this.annotations.length - 1)
					output.append(" "); //$NON-NLS-1$
			}
			output.append('\n');
		}
		if (isOpen()) {
			output.append("open "); //$NON-NLS-1$
		}
		output.append("module "); //$NON-NLS-1$
		output.append(CharOperation.charToString(this.moduleName));
		return output;
	}
	public StringBuffer printBody(int indent, StringBuffer output) {
		output.append(" {"); //$NON-NLS-1$
		if (this.requires != null) {
			for(int i = 0; i < this.requiresCount; i++) {
				output.append('\n');
				printIndent(indent + 1, output);
				this.requires[i].print(0, output);
			}
		}
		if (this.exports != null) {
			for(int i = 0; i < this.exportsCount; i++) {
				output.append('\n');
				this.exports[i].print(indent + 1, output);
			}
		}
		if (this.opens != null) {
			for(int i = 0; i < this.opensCount; i++) {
				output.append('\n');
				this.opens[i].print(indent + 1, output);
			}
		}
		if (this.uses != null) {
			for(int i = 0; i < this.usesCount; i++) {
				output.append('\n');
				this.uses[i].print(indent + 1, output);
			}
		}
		if (this.servicesCount != 0) {
			for(int i = 0; i < this.servicesCount; i++) {
				output.append('\n');
				this.services[i].print(indent + 1, output);
			}
		}
		output.append('\n');
		return printIndent(indent, output).append('}');
	}

	@Override
	public StringBuffer print(int indent, StringBuffer output) {
		//
		printIndent(indent, output);
		printHeader(0, output);
		return printBody(indent, output);
	}
}
