/*
 * Copyright 2011 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.util;

import com.sylvanaar.idea.Lua.lang.psi.expressions.*;
import com.sylvanaar.idea.Lua.lang.psi.impl.statements.*;
import com.sylvanaar.idea.Lua.lang.psi.lists.*;
import com.sylvanaar.idea.Lua.lang.psi.statements.*;
import com.sylvanaar.idea.Lua.lang.psi.symbols.*;
import com.sylvanaar.idea.Lua.lang.psi.types.*;
import com.sylvanaar.idea.Lua.util.LuaAtomicNotNullLazyValue;
import org.jetbrains.annotations.*;

import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: Jon S Akhtar
 * Date: 6/8/11
 * Time: 12:49 PM
 */
public class LuaAssignmentUtil {
    @NotNull
    public static LuaAssignment[] getAssignments(LuaAssignmentStatement assignmentStatement) {
        LuaExpressionList exprs = assignmentStatement.getRightExprs();

        if (exprs == null)
            return LuaAssignment.EMPTY_ARRAY;

        List<LuaExpression> vals = exprs.getLuaExpressions();

        if (vals.size() == 0)
            return LuaAssignment.EMPTY_ARRAY;

        LuaIdentifierList leftExprs = assignmentStatement.getLeftExprs();
        if (leftExprs == null)
            return LuaAssignment.EMPTY_ARRAY;

        LuaSymbol[] defs = leftExprs.getSymbols();

        LuaAssignment[] assignments = new LuaAssignment[Math.min(vals.size(), defs.length)];

        for(int i=0;i<assignments.length; i++)
            assignments[i]= new LuaAssignment(defs[i], vals.get(i));

        return assignments;
    }

    public static LuaExpression[] getDefinedSymbolValues(LuaAssignmentStatementImpl assignmentStmt) {
        LuaExpressionList exprs = assignmentStmt.getRightExprs();

        if (exprs == null) return LuaExpression.EMPTY_ARRAY;

        List<LuaExpression> vals = exprs.getLuaExpressions();

        return vals.toArray(new LuaExpression[vals.size()]);
    }

    public static void transferTypes(LuaAssignmentStatement statement) {
        for (LuaAssignment a : statement.getAssignments()) {
            final LuaSymbol symbol = a.getSymbol();
            final LuaType lType = symbol.getLuaType();
            final LuaType rType = a.getValue().getLuaType();

            transferSingleType(a.getValue(), symbol, lType, rType);
        }
    }

    public static void transferSingleType(LuaExpression value, LuaSymbol symbol, LuaType lType, LuaType rType) {
        if (symbol instanceof Assignable)
            symbol.setLuaType(rType);
        else
            symbol.setLuaType(LuaTypeUtil.combineTypes(lType, rType));

        if (symbol instanceof LuaAlias)
            ((LuaAlias) symbol).setAliasElement(value);
    }

    public static class Assignments extends LuaAtomicNotNullLazyValue<LuaAssignment[]> {
        private LuaAssignmentStatement assignment;

        public Assignments(LuaAssignmentStatement assignment) {this.assignment = assignment;}

        @NotNull
        @Override
        protected LuaAssignment[] compute() {
            return getAssignments(assignment);
        }
    }
}

@@ -677,24 +677,107 @@
 si.util;%0D%0A%0D%0A
+import com.intellij.openapi.project.*;%0D%0Aimport com.sylvanaar.idea.Lua.lang.psi.*;%0D%0A
 import com.s
@@ -1120,33 +1120,9 @@
 til.
-LuaAtomicNotNullLazyValue
+*
 ;%0D%0Ai
@@ -1313,16 +1313,191 @@
 ntUtil %7B
+%0D%0A%0D%0A    private static LuaExpression getImpliedNil(Project project) %7B%0D%0A        return LuaPsiElementFactory.getInstance(project).createExpressionFromText(%22nil%22);%0D%0A    %7D%0D%0A%0D%0A%0D%0A%0D%0A
 %0D%0A    @N
@@ -1686,121 +1686,92 @@
     
-if (
+List%3CLuaExpression%3E vals = 
 exprs 
-=
+!
 = null
-)%0D%0A            return LuaAssignment.EMPTY_ARRAY;%0D%0A%0D%0A        List%3CLuaExpression%3E vals = exprs.get
+ ? exprs.getLuaExpressions() : Collections.%3C
 LuaE
@@ -1771,33 +1771,42 @@
 s.%3CLuaExpression
-s
+%3EemptyList
 ();%0D%0A%0D%0A        i
@@ -1808,75 +1808,39 @@
     
-if (vals.size() == 0)%0D%0A            return LuaAssignment.EMPTY_ARRAY
+final int numVals = vals.size()
 ;%0D%0A%0D
@@ -1945,16 +1945,18 @@
 == null)
+ %7B
 %0D%0A      
@@ -1987,32 +1987,43 @@
 nt.EMPTY_ARRAY;%0D
+%0A        %7D%0D
 %0A%0D%0A        LuaSy
@@ -2123,30 +2123,8 @@
 ent%5B
-Math.min(vals.size(), 
 defs
@@ -2130,17 +2130,16 @@
 s.length
-)
 %5D;%0D%0A%0D%0A  
@@ -2151,19 +2151,25 @@
  for
+ 
 (int i
-=0;i%3C
+ = 0; i %3C 
 assi
@@ -2188,16 +2188,18 @@
 th; i++)
+ %7B
 %0D%0A      
@@ -2218,16 +2218,17 @@
 ments%5Bi%5D
+ 
 = new Lu
@@ -2252,21 +2252,96 @@
 i%5D, 
-vals.get(i));
+i %3C numVals ? vals.get(i) : getImpliedNil(assignmentStatement.getProject()));%0D%0A        %7D
 %0D%0A%0D%0A

Build the assignment list including the implied nils