/*
 * Copyright 2009-2010 by The Regents of the University of California
 * 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 from
 * 
 *     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 edu.uci.ics.asterix.optimizer.rules;

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

import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;

import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;

/**
 * This rule is to inline unnest functions that are hold by variables.
 * This rule is to fix issue 201.
 */
public class InlineUnnestFunctionRule implements IAlgebraicRewriteRule {

    @Override
    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
        return false;
    }

    @Override
    public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
            throws AlgebricksException {
        AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
        if (context.checkIfInDontApplySet(this, op1))
            return false;
        context.addToDontApplySet(this, op1);
        if (op1.getOperatorTag() != LogicalOperatorTag.UNNEST)
            return false;
        UnnestOperator unnestOperator = (UnnestOperator) op1;
        AbstractFunctionCallExpression expr = (AbstractFunctionCallExpression) unnestOperator.getExpressionRef()
                .getValue();
        //we only inline for the scan-collection function
        if (expr.getFunctionIdentifier() != AsterixBuiltinFunctions.SCAN_COLLECTION)
            return false;

        // inline all variables from an unnesting function call
        AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
        List<Mutable<ILogicalExpression>> args = funcExpr.getArguments();
        for (int i = 0; i < args.size(); i++) {
            ILogicalExpression argExpr = args.get(i).getValue();
            if (argExpr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
                VariableReferenceExpression varExpr = (VariableReferenceExpression) argExpr;
                inlineVariable(varExpr.getVariableReference(), unnestOperator);
            }
        }
        return true;
    }

    /**
     * This method is to inline one variable
     * 
     * @param usedVar
     *            A variable that is used by the scan-collection function in the unnest operator
     * @param unnestOp
     *            The unnest operator.
     * @throws AlgebricksException
     */
    private void inlineVariable(LogicalVariable usedVar, UnnestOperator unnestOp) throws AlgebricksException {
        AbstractFunctionCallExpression expr = (AbstractFunctionCallExpression) unnestOp.getExpressionRef().getValue();
        List<Pair<AbstractFunctionCallExpression, Integer>> parentAndIndexList = new ArrayList<Pair<AbstractFunctionCallExpression, Integer>>();
        getParentFunctionExpression(usedVar, expr, parentAndIndexList);
        ILogicalExpression usedVarOrginExpr = findUsedVarOrigin(usedVar, unnestOp, (AbstractLogicalOperator) unnestOp
                .getInputs().get(0).getValue());
        if (usedVarOrginExpr != null) {
            for (Pair<AbstractFunctionCallExpression, Integer> parentAndIndex : parentAndIndexList) {
                //we only rewrite the top scan-collection function
                if (parentAndIndex.first.getFunctionIdentifier() == AsterixBuiltinFunctions.SCAN_COLLECTION
                        && parentAndIndex.first == expr) {
                    unnestOp.getExpressionRef().setValue(usedVarOrginExpr);
                }
            }
        }
    }

    private void getParentFunctionExpression(LogicalVariable usedVar, ILogicalExpression expr,
            List<Pair<AbstractFunctionCallExpression, Integer>> parentAndIndexList) {
        AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
        List<Mutable<ILogicalExpression>> args = funcExpr.getArguments();
        for (int i = 0; i < args.size(); i++) {
            ILogicalExpression argExpr = args.get(i).getValue();
            if (argExpr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
                VariableReferenceExpression varExpr = (VariableReferenceExpression) argExpr;
                if (varExpr.getVariableReference().equals(usedVar))
                    parentAndIndexList.add(new Pair<AbstractFunctionCallExpression, Integer>(funcExpr, i));
            }
            if (argExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
                getParentFunctionExpression(usedVar, argExpr, parentAndIndexList);
            }
        }
    }

    private ILogicalExpression findUsedVarOrigin(LogicalVariable usedVar, AbstractLogicalOperator parentOp,
            AbstractLogicalOperator currentOp) throws AlgebricksException {
        ILogicalExpression ret = null;
        if (currentOp.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
            List<LogicalVariable> producedVars = new ArrayList<LogicalVariable>();
            VariableUtilities.getProducedVariables(currentOp, producedVars);
            if (producedVars.contains(usedVar)) {
                AssignOperator assignOp = (AssignOperator) currentOp;
                int index = assignOp.getVariables().indexOf(usedVar);
                ILogicalExpression returnedExpr = assignOp.getExpressions().get(index).getValue();
                if (returnedExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
                    AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) returnedExpr;
                    if (AsterixBuiltinFunctions.isBuiltinUnnestingFunction(funcExpr.getFunctionIdentifier())) {
                        // we only inline for unnest functions
                        removeUnecessaryAssign(parentOp, currentOp, assignOp, index);
                        ret = returnedExpr;
                    }
                } else if (returnedExpr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
                    //recusively inline
                    VariableReferenceExpression varExpr = (VariableReferenceExpression) returnedExpr;
                    LogicalVariable var = varExpr.getVariableReference();
                    ILogicalExpression finalExpr = findUsedVarOrigin(var, currentOp,
                            (AbstractLogicalOperator) currentOp.getInputs().get(0).getValue());
                    if (finalExpr != null) {
                        removeUnecessaryAssign(parentOp, currentOp, assignOp, index);
                        ret = finalExpr;
                    }
                }
            }
        } else {
            for (Mutable<ILogicalOperator> child : currentOp.getInputs()) {
                ILogicalExpression expr = findUsedVarOrigin(usedVar, currentOp,
                        (AbstractLogicalOperator) child.getValue());
                if (expr != null) {
                    ret = expr;
                }
            }
        }
        return ret;
    }

    private void removeUnecessaryAssign(AbstractLogicalOperator parentOp, AbstractLogicalOperator currentOp,
            AssignOperator assignOp, int index) {
        assignOp.getVariables().remove(index);
        assignOp.getExpressions().remove(index);
        if (assignOp.getVariables().size() == 0) {
            int opIndex = parentOp.getInputs().indexOf(new MutableObject<ILogicalOperator>(currentOp));
            parentOp.getInputs().get(opIndex).setValue(assignOp.getInputs().get(0).getValue());
        }
    }
}
