/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.vxquery.compiler.rewriter.rules.util;

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

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.vxquery.compiler.algebricks.VXQueryConstantValue;
import org.apache.vxquery.context.StaticContext;
import org.apache.vxquery.datamodel.accessors.TaggedValuePointable;
import org.apache.vxquery.functions.BuiltinFunctions;
import org.apache.vxquery.functions.BuiltinOperators;
import org.apache.vxquery.functions.Function;
import org.apache.vxquery.types.AnyNodeType;
import org.apache.vxquery.types.Quantifier;
import org.apache.vxquery.types.SequenceType;

import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractAssignOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
import org.apache.hyracks.data.std.primitive.IntegerPointable;

public class ExpressionToolbox {
    public static Mutable<ILogicalExpression> findVariableExpression(Mutable<ILogicalExpression> mutableLe,
            LogicalVariable lv) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
            VariableReferenceExpression vre = (VariableReferenceExpression) le;
            if (vre.getVariableReference() == lv) {
                return mutableLe;
            }
        } else if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
                Mutable<ILogicalExpression> resultLe = findVariableExpression(argExp, lv);
                if (resultLe != null) {
                    return resultLe;
                }
            }
        }
        return null;
    }

    public static Mutable<ILogicalExpression> findVariableExpression(Mutable<ILogicalExpression> mutableLe) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
            return mutableLe;
        } else if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
                Mutable<ILogicalExpression> resultLe = findVariableExpression(argExp);
                if (resultLe != null) {
                    return resultLe;
                }
            }
        }
        return null;
    }

    public static void findVariableExpressions(Mutable<ILogicalExpression> mutableLe,
            List<Mutable<ILogicalExpression>> finds) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
            finds.add(mutableLe);
        } else if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
                findVariableExpressions(argExp, finds);
            }
        }
    }

    public static Mutable<ILogicalExpression> findLastFunctionExpression(Mutable<ILogicalExpression> mutableLe) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
            return null;
        } else if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
                if (argExp.getValue().getExpressionTag() == LogicalExpressionTag.VARIABLE) {
                    return mutableLe;
                }
                Mutable<ILogicalExpression> resultLe = findLastFunctionExpression(argExp);
                if (resultLe != null) {
                    return resultLe;
                }
            }
        }
        return null;
    }

    public static Mutable<ILogicalExpression> findFirstFunctionExpression(Mutable<ILogicalExpression> mutableLe,
            FunctionIdentifier fi) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
            if (afce.getFunctionIdentifier().equals(fi)) {
                return mutableLe;
            }
            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
                Mutable<ILogicalExpression> resultLe = findFirstFunctionExpression(argExp, fi);
                if (resultLe != null) {
                    return resultLe;
                }
            }
        }
        return null;
    }

    /**
     * Finds all functions for a given expression.
     *
     * @param mutableLe
     *            Search logical expression
     * @param finds
     *            Logical expressions found
     */
    public static void findAllFunctionExpressions(Mutable<ILogicalExpression> mutableLe,
            List<Mutable<ILogicalExpression>> finds) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
            finds.add(mutableLe);
            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
                findAllFunctionExpressions(argExp, finds);
            }
        }
    }

    /**
     * Finds all functions for a given expression and function identifier.
     *
     * @param mutableLe
     *            Search logical expression
     * @param fi
     *            Function indentifier
     * @param finds
     *            Logical expressions found
     */
    public static void findAllFunctionExpressions(Mutable<ILogicalExpression> mutableLe, FunctionIdentifier fi,
            List<Mutable<ILogicalExpression>> finds) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
            if (afce.getFunctionIdentifier().equals(fi)) {
                finds.add(mutableLe);
            }
            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
                findAllFunctionExpressions(argExp, fi, finds);
            }
        }
    }

    public static Function getBuiltIn(Mutable<ILogicalExpression> mutableLe) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
            for (Function function : BuiltinFunctions.FUNCTION_COLLECTION) {
                if (function.getFunctionIdentifier().equals(afce.getFunctionIdentifier())) {
                    return function;
                }
            }
            for (Function function : BuiltinOperators.OPERATOR_COLLECTION) {
                if (function.getFunctionIdentifier().equals(afce.getFunctionIdentifier())) {
                    return function;
                }
            }
        }
        return null;
    }

    public static void getConstantAsPointable(ConstantExpression typeExpression, TaggedValuePointable tvp) {
        VXQueryConstantValue treatTypeConstant = (VXQueryConstantValue) typeExpression.getValue();
        tvp.set(treatTypeConstant.getValue(), 0, treatTypeConstant.getValue().length);
    }

    public static int getTypeExpressionTypeArgument(Mutable<ILogicalExpression> searchM) {
        final int ARG_TYPE = 1;
        AbstractFunctionCallExpression searchFunction = (AbstractFunctionCallExpression) searchM.getValue();
        ILogicalExpression argType = searchFunction.getArguments().get(ARG_TYPE).getValue();
        if (argType.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
            return -1;
        }
        TaggedValuePointable tvp = (TaggedValuePointable) TaggedValuePointable.FACTORY.createPointable();
        ExpressionToolbox.getConstantAsPointable((ConstantExpression) argType, tvp);

        IntegerPointable pTypeCode = (IntegerPointable) IntegerPointable.FACTORY.createPointable();
        tvp.getValue(pTypeCode);
        return pTypeCode.getInteger();
    }

    public static Byte[] getConstantArgument(Mutable<ILogicalExpression> searchM, int arg) {
        AbstractFunctionCallExpression searchFunction = (AbstractFunctionCallExpression) searchM.getValue();
        ILogicalExpression argType = searchFunction.getArguments().get(arg).getValue();
        searchFunction.getArguments().size();
        if (argType.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
            return null;
        }
        TaggedValuePointable tvp = (TaggedValuePointable) TaggedValuePointable.FACTORY.createPointable();
        ExpressionToolbox.getConstantAsPointable((ConstantExpression) argType, tvp);
        return ArrayUtils.toObject(tvp.getByteArray());
    }

    public static List<ILogicalExpression> getFullArguments(Mutable<ILogicalExpression> searchM) {
        AbstractFunctionCallExpression searchFunction = (AbstractFunctionCallExpression) searchM.getValue();
        ArrayList<ILogicalExpression> args = new ArrayList<ILogicalExpression>();
        for (int i = 0; i < searchFunction.getArguments().size(); i++) {
            args.add(searchFunction.getArguments().get(i).getValue());
        }
        return args;
    }

    public static SequenceType getTypeExpressionTypeArgument(Mutable<ILogicalExpression> searchM, StaticContext dCtx) {
        int typeId = getTypeExpressionTypeArgument(searchM);
        if (typeId > 0) {
            return dCtx.lookupSequenceType(typeId);
        } else {
            return null;
        }
    }

    public static SequenceType getOutputSequenceType(Mutable<ILogicalOperator> opRef,
            Mutable<ILogicalExpression> argFirstM, StaticContext dCtx) {
        ILogicalExpression argFirstLe = argFirstM.getValue();
        switch (argFirstLe.getExpressionTag()) {
            case FUNCTION_CALL:
                // Only process defined functions.
                Function function = ExpressionToolbox.getBuiltIn(argFirstM);
                if (function == null) {
                    return null;
                } else if (function.getFunctionIdentifier().equals(BuiltinOperators.CAST.getFunctionIdentifier())) {
                    // Special case since case has multiple type outputs.
                    return ExpressionToolbox.getTypeExpressionTypeArgument(argFirstM, dCtx);
                } else {
                    return function.getSignature().getReturnType();
                }
            case CONSTANT:
                // Consider constant values.
                ConstantExpression constantExpression = (ConstantExpression) argFirstLe;
                VXQueryConstantValue constantValue = (VXQueryConstantValue) constantExpression.getValue();
                return constantValue.getType();
            case VARIABLE:
                VariableReferenceExpression variableRefExp = (VariableReferenceExpression) argFirstLe;
                LogicalVariable variableId = variableRefExp.getVariableReference();
                Mutable<ILogicalOperator> variableProducer = OperatorToolbox.findProducerOf(opRef, variableId);
                if (variableProducer == null) {
                    return null;
                }
                AbstractLogicalOperator variableOp = (AbstractLogicalOperator) variableProducer.getValue();
                switch (variableOp.getOperatorTag()) {
                    case ASSIGN:
                    case AGGREGATE:
                    case RUNNINGAGGREGATE:
                        AbstractAssignOperator assign = (AbstractAssignOperator) variableOp;
                        for (int i = 0; i < assign.getVariables().size(); ++i) {
                            if (variableId.equals(assign.getVariables().get(i))) {
                                return getOutputSequenceType(variableProducer, assign.getExpressions().get(i), dCtx);
                            }
                        }
                        return null;
                    case DATASOURCESCAN:
                        return SequenceType.create(AnyNodeType.INSTANCE, Quantifier.QUANT_ONE);
                    case UNNEST:
                        UnnestOperator unnest = (UnnestOperator) variableOp;
                        return getOutputSequenceType(variableProducer, unnest.getExpressionRef(), dCtx);
                    default:
                        // TODO Consider support for other operators. i.e. Assign.
                        break;
                }

        }
        return null;
    }

    public static boolean isFunctionExpression(Mutable<ILogicalExpression> mutableLe,
            AbstractFunctionCallExpression afce) {
        ILogicalExpression le = mutableLe.getValue();
        if (le.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
            return false;
        }
        AbstractFunctionCallExpression fc = (AbstractFunctionCallExpression) le;
        if (!fc.getFunctionIdentifier().equals(afce)) {
            return false;
        }
        return true;
    }
}
