/*
 * Copyright 2010 Jon S Akhtar (Sylvanaar)
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package com.sylvanaar.idea.Lua.lang.psi.impl.statements;

import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.ResolveState;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.sylvanaar.idea.Lua.lang.parser.LuaElementTypes;
import com.sylvanaar.idea.Lua.lang.psi.expressions.LuaIdentifier;
import com.sylvanaar.idea.Lua.lang.psi.expressions.LuaParameter;
import com.sylvanaar.idea.Lua.lang.psi.expressions.LuaParameterList;
import com.sylvanaar.idea.Lua.lang.psi.impl.expressions.LuaImpliedSelfParameterImpl;
import com.sylvanaar.idea.Lua.lang.psi.statements.LuaBlock;
import com.sylvanaar.idea.Lua.lang.psi.statements.LuaFunctionDefinitionStatement;
import com.sylvanaar.idea.Lua.lang.psi.visitor.LuaElementVisitor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * Created by IntelliJ IDEA.
 * User: Jon S Akhtar
 * Date: Jun 10, 2010
 * Time: 10:40:55 AM
 */
public class LuaFunctionDefinitionStatementImpl extends LuaStatementElementImpl implements LuaFunctionDefinitionStatement/*, PsiModifierList */ {
    private LuaParameterList parameters = null;
    private LuaIdentifier identifier = null;
    private LuaBlock block = null;
    private boolean definesSelf = false;

    public LuaFunctionDefinitionStatementImpl(ASTNode node) {
        super(node);

        assert getBlock() != null;
    }

    public void accept(LuaElementVisitor visitor) {
        visitor.visitFunctionDef(this);
    }

    public void accept(@NotNull PsiElementVisitor visitor) {
        if (visitor instanceof LuaElementVisitor) {
            ((LuaElementVisitor) visitor).visitFunctionDef(this);
        } else {
            visitor.visitElement(this);
        }
    }


    

    public boolean processDeclarations(@NotNull PsiScopeProcessor processor,
                                       @NotNull ResolveState resolveState,
                                       PsiElement lastParent,
                                       @NotNull PsiElement place) {

       if (lastParent != null && lastParent.getParent() == this) {
         final LuaParameter[] params = getParameters().getParameters();
         for (LuaParameter param : params) {
           if (!processor.execute(param, resolveState)) return false;
         }

         LuaParameter self = findChildByClass(LuaImpliedSelfParameterImpl.class);

         if (self != null) {
             if (!processor.execute(self, resolveState)) return false;
         }
       }

        if (!getBlock().processDeclarations(processor, resolveState, lastParent, place))
                return false;

       if (!getIdentifier().isLocal())
        return true;
        
       return processor.execute(this, resolveState);
    }


    @Nullable
    @NonNls
    public String getName() {
        LuaIdentifier name = getIdentifier();

        return name != null ? name.getName() : "anonymous";
    }

    @Override
    public PsiElement setName(String s) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }


    @Override
    public LuaIdentifier getIdentifier() {
        if (identifier == null) {
            LuaIdentifier e = findChildByClass(LuaIdentifier.class);
            if (e != null)
                identifier = e;
        }
        return identifier;
    }

    @Override
    public LuaParameterList getParameters() {
        if (parameters == null) {
            PsiElement e = findChildByType(LuaElementTypes.PARAMETER_LIST);
            if (e != null)
                parameters = (LuaParameterList) e;
        }
        return parameters;
    }

    public LuaBlock getBlock() {
        if (block == null) {
            PsiElement e = findChildByType(LuaElementTypes.BLOCK);
            if (e != null)
                block = (LuaBlock) e;
        }
        return block;
    }


    @Override
    public String toString() {
        return "Function Declaration (" + getIdentifier() + ")";
    }
}

@@ -1156,24 +1156,89 @@
 meterList;%0D%0A
+import com.sylvanaar.idea.Lua.lang.psi.expressions.LuaVariable;%0D%0A
 import com.s
@@ -1972,26 +1972,24 @@
 vate Lua
-Identifier
+Variable
  identif
@@ -3543,24 +3543,16 @@
  true;%0D%0A
-        
 %0D%0A      
@@ -4067,26 +4067,24 @@
      Lua
-Identifier
+Variable
  e = fin
@@ -4100,26 +4100,24 @@
 lass(Lua
-Identifier
+Variable
 .class);

the function identifier is a variable not an identifier.