/*
 * generated by Xtext
 */
package org.eclipselabs.mscript.language.scoping;

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

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.Scopes;
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
import org.eclipselabs.mscript.language.ast.FeatureCall;
import org.eclipselabs.mscript.language.ast.FunctionDefinition;
import org.eclipselabs.mscript.language.ast.FunctionObjectDeclaration;
import org.eclipselabs.mscript.language.ast.IterationCall;
import org.eclipselabs.mscript.language.ast.LetExpression;
import org.eclipselabs.mscript.language.ast.LetExpressionVariableDeclaration;
import org.eclipselabs.mscript.language.ast.LetExpressionVariableDeclarationPart;
import org.eclipselabs.mscript.language.ast.ParameterDeclaration;
import org.eclipselabs.mscript.language.ast.StateVariableDeclaration;

public class MscriptScopeProvider extends AbstractDeclarativeScopeProvider {

	public IScope scope_FeatureCall_feature(FeatureCall context, EReference reference) {
		List<EObject> elements = new ArrayList<EObject>();
		
		EObject container = context.eContainer();
		while (container != null) {
			if (container instanceof LetExpression) {
				LetExpression letExpression = (LetExpression) container;
				for (LetExpressionVariableDeclaration variableDeclaration : letExpression.getVariableDeclarations()) {
					for (LetExpressionVariableDeclarationPart part : variableDeclaration.getParts()) {
						elements.add(part);
					}
				}
			} else if (container instanceof IterationCall) {
				IterationCall iterationCall = (IterationCall) container;
				elements.add(iterationCall.getAccumulator());
				elements.addAll(iterationCall.getVariables());
			} else if (container instanceof FunctionDefinition) {
				FunctionDefinition functionDefinition = (FunctionDefinition) container;

				for (StateVariableDeclaration stateVariableDeclaration : functionDefinition.getStateVariableDeclarations()) {
					elements.add(stateVariableDeclaration);
				}

				for (FunctionObjectDeclaration functionObjectDeclaration : functionDefinition.getFunctionObjectDeclarations()) {
					elements.add(functionObjectDeclaration);
				}

				for (ParameterDeclaration parameterDeclaration : functionDefinition.getTemplateParameterDeclarations()) {
					elements.add(parameterDeclaration);
				}
				
				for (ParameterDeclaration parameterDeclaration : functionDefinition.getInputParameterDeclarations()) {
					elements.add(parameterDeclaration);
				}
				
				for (ParameterDeclaration parameterDeclaration : functionDefinition.getOutputParameterDeclarations()) {
					elements.add(parameterDeclaration);
				}

				elements.add(functionDefinition);
			}
			container = container.eContainer();
		}
		
		return Scopes.scopeFor(elements, getDelegate().getScope(context, reference));
	}

}
