/*
 * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.jpa.parsing;

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

// TopLink imports
import org.eclipse.persistence.exceptions.JPQLException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReportQuery;

/**
 * INTERNAL
 * <p><b>Purpose</b>: The node that represents typed variables, local variables, remote variables and TYPE constants.
 *
 *    @author Jon Driscoll and Joel Lucuik
 *    @since TopLink 4.0
 */
public class VariableNode extends Node implements AliasableNode {

    /** */
    private String variableName;

    /** */
    private String canonicalName;

    /** if this represents a type constant, this value will be populated by validate **/
    private Object classConstant = null;

    /**
     * VariableNode constructor comment.
     */
    public VariableNode() {
        super();
    }

    public VariableNode(String newVariableName) {
        setVariableName(newVariableName);
    }

    public String getVariableName() {
        return variableName;
    }

    public void setVariableName(String newVariableName) {
        variableName = newVariableName;
        canonicalName = IdentificationVariableDeclNode.calculateCanonicalName(newVariableName);
    }

    /** */
    public String getCanonicalVariableName() {
        return canonicalName;
    }

    /**
     * INTERNAL
     * Is this node a VariableNode
     */
    @Override
    public boolean isVariableNode() {
        return true;
    }

    /**
     * INTERNAL
     * Apply this node to the passed query
     */
    @Override
    public void applyToQuery(ObjectLevelReadQuery theQuery, GenerationContext generationContext) {
        String name = getCanonicalVariableName();
        if (theQuery instanceof ReportQuery) {
            ReportQuery reportQuery = (ReportQuery)theQuery;
            Expression expression = generationContext.expressionFor(name);
            if (expression == null) {
                expression = generateExpression(generationContext);
            }
            addAttributeWithFetchJoins(reportQuery, expression, generationContext);
        } else {
            addFetchJoins(theQuery, generationContext);
        }
    }

    /**
     * INTERNAL
     * Add the variable as ReportQuery item. The method checks for any JOIN
     * FETCH nodes of the current variable and adds them as part of the
     * ReportQuery item.
     */
    private void addAttributeWithFetchJoins(ReportQuery reportQuery,
                                            Expression expression,
                                            GenerationContext context) {
        String name = getCanonicalVariableName();
        List fetchJoinNodes = context.getParseTreeContext().getFetchJoins(name);
        if (fetchJoinNodes == null) {
            reportQuery.addAttribute(name, expression);
        } else {
            List fetchJoinExprs = new ArrayList(fetchJoinNodes.size());
            for (Iterator i = fetchJoinNodes.iterator(); i.hasNext(); ) {
                Node node = (Node)i.next();
                fetchJoinExprs.add(node.generateExpression(context));
            }
            reportQuery.addItem(name, expression, fetchJoinExprs);
        }
    }

    /**
     * INTERNAL
     * Check for any JOIN FETCH nodes of the current variable and add them as
     * joined attributes. This method is called in case of a non ReportQuery
     * instance.
     */
    private void addFetchJoins(ObjectLevelReadQuery theQuery,
                               GenerationContext context) {
        String name = getCanonicalVariableName();
        List fetchJoinNodes = context.getParseTreeContext().getFetchJoins(name);
        if (fetchJoinNodes != null) {
            for (Iterator i = fetchJoinNodes.iterator(); i.hasNext(); ) {
                Node node = (Node)i.next();
                theQuery.addJoinedAttribute(node.generateExpression(context));
            }
        }
    }

    /**
     * INTERNAL
     * This node represent an unqualified field access in the case the method
     * is called and the variableName is not defined as identification variable.
     * The method returns a DotNode representing a qualified field access with
     * the base variable as left child node. The right child node is an
     * AttributeNode using the variableName as field name.
     */
    @Override
    public Node qualifyAttributeAccess(ParseTreeContext context) {
        return context.isVariable(variableName) ? this :
            (Node)context.getNodeFactory().newQualifiedAttribute(
                getLine(), getColumn(), context.getBaseVariable(), variableName);
    }

    /**
     * INTERNAL
     * Validate node and calculate its type.
     */
    @Override
    public void validate(ParseTreeContext context) {
        TypeHelper typeHelper = context.getTypeHelper();
        classConstant = typeHelper.resolveSchema(variableName);
        if (classConstant != null){
            setType(Class.class);
            return;
        }
        String name = getCanonicalVariableName();
        if (context.isRangeVariable(name)) {
            String schema = context.schemaForVariable(name);
            setType(typeHelper.resolveSchema(schema));
        } else {
            Node path = context.pathForVariable(name);
            if (path == null) {
                throw JPQLException.aliasResolutionException(
                    context.getQueryInfo(), getLine(), getColumn(), name);
            } else {
                setType(path.getType());
            }
        }
        context.usedVariable(name);
        if (context.isDeclaredInOuterScope(name)) {
            context.registerOuterScopeVariable(name);
        }
    }

    public Expression generateBaseBuilderExpression(GenerationContext context) {
        //create builder, and add it, and answer it
        //BUG 3106877: Need to create builder using the actual class (if using parallel expressions)
        return new ExpressionBuilder(this.resolveClass(context));
    }

    @Override
    public Expression generateExpression(GenerationContext generationContext) {
        Expression myExpression = null;
        String name = getCanonicalVariableName();

        //is there a cached Expression?
        myExpression = generationContext.expressionFor(name);
        if (myExpression != null) {
            return myExpression;
        }

        //Either I have an alias type, or I'm an IN declaration
        if (classConstant != null){
            myExpression = new ConstantExpression(classConstant, generationContext.getBaseExpression());
        } else if (generationContext.getParseTreeContext().isRangeVariable(name)) {
            myExpression = generateBaseBuilderExpression(generationContext);
        } else {
            myExpression = generateExpressionForAlias(generationContext);
        }

        generationContext.addExpression(myExpression, name);
        return myExpression;
    }

    public Expression generateExpressionForAlias(GenerationContext context) {
        // BUG 3105651: Verify if we need to resolve this alias, or just use
        // an empty ExpressionBuilder. See OrderByItemNode.generateExpression()
        // for more details
        if (context.getParseTree().getQueryNode().isSelectNode() && context.shouldCheckSelectNodeBeforeResolving() && (((SelectNode)context.getParseTree().getQueryNode()).isSelected(this.getCanonicalVariableName()))) {
            return new ExpressionBuilder();
        }

        Node nodeForAlias = getNodeForAlias(context);

        //assume that if there is no node available for the given variable, then
        //there must be an alias mismatch. Assume they know their attribute names better
        //than their alias names. - JGL
        if (nodeForAlias == null) {
            throw JPQLException.aliasResolutionException(
                context.getParseTreeContext().getQueryInfo(),
                getLine(), getColumn(), getVariableName());
        }

        //create builder, and answer it
        return nodeForAlias.generateExpression(context);
    }

    public Node getNodeForAlias(GenerationContext context) {
        //Node node = context.getParseTreeContext().nodeForIdentifier(getCanonicalVariableName());
        //return node != null ? ((IdentificationVariableDeclNode)node).getPath() : null;
        return context.getParseTreeContext().pathForVariable(getCanonicalVariableName());
    }

    /**
     * isAlias: Answer true if this variable represents an alias in the FROM clause.
     * i.e. "FROM Employee emp" declares "emp" as an alias
     */
    public boolean isAlias(GenerationContext context) {
        return isAlias(context.getParseTreeContext());
    }

    public boolean isAlias(ParseTreeContext context) {
        String classNameForAlias = context.schemaForVariable(getCanonicalVariableName());
        return classNameForAlias != null;
    }

    /**
     * resolveClass: Answer the class which corresponds to my variableName. This is the class for
     * an alias, where the variableName is registered to an alias.
     */
    @Override
    public Class resolveClass(GenerationContext generationContext) {
        Class clazz = null;
        String name = getCanonicalVariableName();
        ParseTreeContext context = generationContext.getParseTreeContext();
        if (context.isRangeVariable(name)) {
            String schema = context.schemaForVariable(name);
            clazz = context.classForSchemaName(schema, generationContext);
        } else {
            DotNode path = (DotNode)context.pathForVariable(name);
            if (path == null) {
                throw JPQLException.aliasResolutionException(
                    context.getQueryInfo(), getLine(), getColumn(), name);
            } else {
                clazz = path.resolveClass(generationContext);
            }
        }
        return clazz;
    }

    @Override
    public String toString(int indent) {
        StringBuilder buffer = new StringBuilder();
        toStringIndent(indent, buffer);
        buffer.append(toStringDisplayName() + "[" + getVariableName() + "]");
        return buffer.toString();
    }

    /**
     * INTERNAL
     * Get the string representation of this node.
     */
    @Override
    public String getAsString() {
        return getVariableName();
    }

    public Object getTypeForMapKey(ParseTreeContext context){
        String name = getCanonicalVariableName();
        if (context.isRangeVariable(name)) {
            throw JPQLException.variableCannotHaveMapKey(context.getQueryInfo(), getLine(), getColumn(), name);
        } else {
            DotNode path = (DotNode)context.pathForVariable(name);
            if (path == null) {
                throw JPQLException.aliasResolutionException(
                    context.getQueryInfo(), getLine(), getColumn(), name);
            } else {
                return path.getTypeForMapKey(context);
            }
        }
    }


    @Override
    public boolean isAliasableNode(){
        return true;
    }
}
