package com.redhat.ceylon.compiler.js;

import java.util.Set;

import com.redhat.ceylon.compiler.typechecker.model.Declaration;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;

public class Destructurer extends Visitor {

    private final GenerateJsVisitor gen;
    private final JsIdentifierNames names;
    private final String expvar;
    private final Set<Declaration> directAccess;
    private boolean first;

    public Destructurer(final Tree.Pattern that, final GenerateJsVisitor gen,
            final Set<Declaration> directAccess, final String expvar, boolean first) {
        this.gen = gen;
        names = gen == null ? null : gen.getNames();
        this.directAccess = directAccess;
        this.expvar = expvar;
        this.first=first;
        that.visit(this);
    }

    public void visit(final Tree.TuplePattern that) {
        int idx=0;
        for (Tree.Pattern p : that.getPatterns()) {
            if (p instanceof Tree.VariablePattern) {
                p.visit(this);
                if (gen != null) {
                    if (((Tree.VariablePattern)p).getVariable().getType() instanceof Tree.SequencedType) {
                        gen.out(".spanFrom(");
                    } else {
                        gen.out(".$_get(");
                    }
                    gen.out(Integer.toString(idx++), ")");
                }
            } else {
                new Destructurer(p, gen, directAccess, expvar+".$_get("+(idx++)+")", first && idx==0);
            }
        }
    }

    public void visit(final Tree.KeyValuePattern that) {
        if (that.getKey() instanceof Tree.VariablePattern) {
            that.getKey().visit(this);
            if (gen != null) {
                gen.out(".key");
            }
        } else {
            new Destructurer(that.getKey(), gen, directAccess, expvar+".item", first);
        }
        if (that.getValue() instanceof Tree.VariablePattern) {
            that.getValue().visit(this);
            if (gen != null) {
                gen.out(".item");
            }
        } else {
            new Destructurer(that.getValue(), gen, directAccess, expvar+".item", false);
        }
    }

    public void visit(final Tree.VariablePattern that) {
        directAccess.add(that.getVariable().getDeclarationModel());
        if (first) {
            first=false;
        } else if (gen != null) {
            gen.out(",");
        }
        if (gen != null) {
            gen.out(names.name(that.getVariable().getDeclarationModel()), "=",expvar);
        }
    }

}

@@ -33,16 +33,42 @@
 er.js;%0A%0A
+import java.util.HashSet;%0A
 import j
@@ -81,16 +81,16 @@
 il.Set;%0A
-
 %0Aimport 
@@ -502,16 +502,76 @@
 n first;
+%0A    private final Set%3CDeclaration%3E added = new HashSet%3C%3E();
 %0A%0A    pu
@@ -1536,32 +1536,45 @@
                 
+added.addAll(
 new Destructurer
@@ -1629,24 +1629,67 @@
 %22)%22,
- first && idx==0
+%0A                        first && idx==0).getDeclarations()
 );%0A 
@@ -1974,32 +1974,45 @@
 e %7B%0A            
+added.addAll(
 new Destructurer
@@ -2068,16 +2068,35 @@
 , first)
+.getDeclarations())
 ;%0A      
@@ -2311,16 +2311,29 @@
         
+added.addAll(
 new Dest
@@ -2399,16 +2399,35 @@
 , false)
+.getDeclarations())
 ;%0A      
@@ -2558,24 +2558,85 @@
 onModel());%0A
+        added.add(that.getVariable().getDeclarationModel());%0A
         if (
@@ -2853,16 +2853,16 @@
 xpvar);%0A
-
         
@@ -2870,10 +2870,87 @@
 %0A    %7D%0A%0A
+    public Set%3CDeclaration%3E getDeclarations() %7B%0A        return added;%0A    %7D%0A%0A
 %7D%0A

store declarations in a set #464