/*
 * Copyright (c) 1998, 2021 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;

// Java imports
import java.util.*;

import org.eclipse.persistence.exceptions.JPQLException;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReportQuery;

/**
 * INTERNAL
 * <p><b>Purpose</b>: Represent a constructor node (NEW)
 * <p><b>Responsibilities</b>:<ul>
 * <li> Generate the correct expression for a constructor
 * </ul>
 */
public class ConstructorNode extends Node implements AliasableNode {

    /** The name of the constructor class. */
    private String className = null;

    /** The list of constructor call argument nodes */
    public List<Node> constructorItems = new ArrayList<>();

    /**
     * Return a new ConstructorNode
     */
    public ConstructorNode(String className) {
        this.className = className;
    }

    /**
     * INTERNAL
     * Apply this node to the passed query
     */
    @Override
    public void applyToQuery(ObjectLevelReadQuery theQuery, GenerationContext context) {
        if (theQuery instanceof ReportQuery) {
            SelectGenerationContext selectContext = (SelectGenerationContext)context;
            ReportQuery reportQuery = (ReportQuery)theQuery;
            reportQuery.beginAddingConstructorArguments(
                getConstructorClass(context.getParseTreeContext()));
            for (Iterator<Node> i = constructorItems.iterator(); i.hasNext();) {
                Node node = i.next();
                if (selectingRelationshipField(node, context)) {
                    selectContext.useOuterJoins();
                }
                node.applyToQuery(reportQuery, context);
                selectContext.dontUseOuterJoins();
            }
            reportQuery.endAddingToConstructorItem();
        }
    }

    /**
     * INTERNAL
     * Validate node and calculate its type.
     */
    @Override
    public void validate(ParseTreeContext context) {
        for (Iterator<Node> i = constructorItems.iterator(); i.hasNext();) {
            Node item = i.next();
            item.validate(context);
        }

        // Resolve constructor class
        TypeHelper typeHelper = context.getTypeHelper();
        Object type = typeHelper.resolveTypeName(className);
        if (type == null) {
            String name = className;
            // check for inner classes
            int index = name.lastIndexOf('.');
            if (index != -1) {
                name = name.substring(0, index) + '$' + name.substring(index+1);
                type = typeHelper.resolveTypeName(name);
            }
        }
        setType(type);
    }

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

    /**
     * INTERNAL
     * Add an Order By Item to this node
     */
    public void addConstructorItem(Node theNode) {
        constructorItems.add(theNode);
    }

    /**
     * INTERNAL
     * Set the list of constructor items of this node.
     */
    public void setConstructorItems(List<Node> items) {
        this.constructorItems = items;
    }

    /**
     * INTERNAL
     * Get the list of constructor items of this node.
     */
    public List<Node> getConstructorItems() {
        return this.constructorItems;
    }

    /**
     * Check the specific constructor class and return its class instance.
     * @exception JPQLException if the specified constructor class could not
     * be found.
     */
    private Class<?> getConstructorClass(ParseTreeContext context) {
        Object type = getType();
        if (type == null) {
            throw JPQLException.constructorClassNotFound(
                context.getQueryInfo(), getLine(), getColumn(), className);
        }
        return (Class<?>)type;
    }

    /**
     * INTERNAL
     */
    private boolean selectingRelationshipField(Node node, GenerationContext context) {
        if ((node == null) || !node.isDotNode()) {
            return false;
        }

        TypeHelper typeHelper = context.getParseTreeContext().getTypeHelper();
        Node path = node.getLeft();
        AttributeNode attribute = (AttributeNode)node.getRight();
        return typeHelper.isRelationship(path.getType(),
                                         attribute.getAttributeName());
    }

    /**
     * INTERNAL
     * Get the string representation of this node.
     */
    @Override
    public String getAsString() {
        StringBuilder repr = new StringBuilder();
        repr.append("NEW ").append(className);
        repr.append("(");
        for (Iterator<Node> i = constructorItems.iterator(); i.hasNext();) {
            Node node = i.next();
            repr.append(node.getAsString());
            if (i.hasNext()) {
                repr.append(", ");
            }
        }
        repr.append(")");
        return repr.toString();
    }

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