package com.redhat.ceylon.compiler.analyzer;

import java.util.Stack;

import com.redhat.ceylon.compiler.model.Class;
import com.redhat.ceylon.compiler.model.CompilationUnit;
import com.redhat.ceylon.compiler.model.Declaration;
import com.redhat.ceylon.compiler.model.Getter;
import com.redhat.ceylon.compiler.model.Interface;
import com.redhat.ceylon.compiler.model.Method;
import com.redhat.ceylon.compiler.model.Parameter;
import com.redhat.ceylon.compiler.model.Scope;
import com.redhat.ceylon.compiler.model.SimpleValue;
import com.redhat.ceylon.compiler.tree.Tree;
import com.redhat.ceylon.compiler.tree.Visitor;
import com.redhat.ceylon.compiler.model.Package;

public class DeclarationVisitor extends Visitor {
	Stack<Scope<Declaration>> declarationScopes = new Stack<Scope<Declaration>>();
	CompilationUnit compilationUnit;
	
	public DeclarationVisitor(Package p) {
		declarationScopes.push(p);
	}
	
	public void visit(Tree.CompilationUnit that) {
		compilationUnit = new CompilationUnit();
		super.visit(that);
	}
	
	@Override
	public void visit(Tree.ClassDeclaration that) {
		Class c = new Class();
		c.setCompilationUnit(compilationUnit);
		c.setName(that.getTypeName().getText());
		Scope<Declaration> scope = declarationScopes.peek();
		c.setContainer(scope);
		scope.getMembers().add(c);
		declarationScopes.push(c);
		super.visit(that);
		declarationScopes.pop();
	}

	@Override
	public void visit(Tree.InterfaceDeclaration that) {
		Interface i = new Interface();
		i.setCompilationUnit(compilationUnit);
		i.setName(that.getTypeName().getText());
		Scope<Declaration> scope = declarationScopes.peek();
		i.setContainer(scope);
		scope.getMembers().add(i);
		declarationScopes.push(i);
		super.visit(that);
		declarationScopes.pop();
	}

	@Override
	public void visit(Tree.MethodDeclaration that) {
		Method m = new Method();
		m.setCompilationUnit(compilationUnit);
		m.setName(that.getMemberName().getText());
		Scope<Declaration> scope = declarationScopes.peek();
		m.setContainer(scope);
		scope.getMembers().add(m);
		declarationScopes.push(m);
		super.visit(that);
		declarationScopes.pop();
	}

	@Override
	public void visit(Tree.AttributeDeclaration that) {
		SimpleValue v = new SimpleValue();
		v.setCompilationUnit(compilationUnit);
		v.setName(that.getMemberName().getText());
		Scope<Declaration> scope = declarationScopes.peek();
		v.setContainer(scope);
		scope.getMembers().add(v);
		super.visit(that);
	}

	@Override
	public void visit(Tree.AttributeGetter that) {
		Getter g = new Getter();
		g.setCompilationUnit(compilationUnit);
		g.setName(that.getMemberName().getText());
		Scope<Declaration> scope = declarationScopes.peek();
		g.setContainer(scope);
		scope.getMembers().add(g);
		declarationScopes.push(g);
		super.visit(that);
		declarationScopes.pop();
	}
	
	@Override
	public void visit(Tree.Parameter that) {
		Parameter p = new Parameter();
		p.setCompilationUnit(compilationUnit);
		p.setName(that.getParameterName().getText());
		Scope<Declaration> scope = declarationScopes.peek();
		p.setContainer(scope);
		scope.getMembers().add(p);
		declarationScopes.push(p);
		super.visit(that);
		declarationScopes.pop();
	}
}

@@ -564,16 +564,75 @@
 e.Tree;%0A
+import com.redhat.ceylon.compiler.tree.Tree.ParameterName;%0A
 import c
@@ -2989,18 +2989,38 @@
 ;%0A%09%09
-p.set
+ParameterName parameter
 Name
-(
+ = 
 that
@@ -3030,32 +3030,124 @@
 tParameterName()
+;%0A%09%09if (parameterName==null) %7B%0A%09%09%09p.setName(%22this%22);%0A%09%09%7D%0A%09%09else %7B%0A%09%09%09p.setName(parameterName
 .getText());%0A%09%09S
@@ -3135,32 +3135,36 @@
 ame.getText());%0A
+%09%09%7D%0A
 %09%09Scope%3CDeclarat
@@ -3333,13 +3333,136 @@
 .pop();%0A
-
 %09%7D%0A
+%09%0A%09//TODO: variables in try, catch, if, for, while blocks%0A%0A%09@Override%0A%09public void visit(Tree.ControlClause that) %7B%0A%09%09%0A%09%7D%0A%0A
 %7D%0A

handle a special case