/*
 * Copyright (c) 2011, 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
//
package org.eclipse.persistence.jpa.jpql.tools.model.query;

import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.COMMA;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.SPACE;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.persistence.jpa.jpql.Assert;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.parser.Expression;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar;
import org.eclipse.persistence.jpa.jpql.parser.VirtualJPQLQueryBNF;
import org.eclipse.persistence.jpa.jpql.tools.TypeHelper;
import org.eclipse.persistence.jpa.jpql.tools.model.DefaultProblem;
import org.eclipse.persistence.jpa.jpql.tools.model.IJPQLQueryBuilder;
import org.eclipse.persistence.jpa.jpql.tools.model.IPropertyChangeListener;
import org.eclipse.persistence.jpa.jpql.tools.model.Problem;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedTypeProvider;
import org.eclipse.persistence.jpa.jpql.tools.spi.IType;
import org.eclipse.persistence.jpa.jpql.tools.spi.ITypeRepository;
import org.eclipse.persistence.jpa.jpql.tools.utility.iterable.SnapshotCloneIterable;
import org.eclipse.persistence.jpa.jpql.utility.CollectionTools;

/**
 * The abstract definition of a {@link StateObject}.
 *
 * @version 2.5
 * @since 2.4
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public abstract class AbstractStateObject implements StateObject {

    /**
     * The object responsible to actually register the listeners and to notify them upon changes made
     * to this {@link StateObject}.
     */
    private ChangeSupport changeSupport;

    /**
     * The {@link StateObject} that is decorating this one by changing its behavior or <code>null</code>
     * if none was set.
     */
    private StateObject decorator;

    /**
     * The parsed object when a JPQL query is parsed and converted into a {@link StateObject} or
     * <code>null</code> when the JPQL query is manually created (i.e. not from a string).
     */
    private Expression expression;

    /**
     * The parent of this state object.
     */
    private StateObject parent;

    /**
     * Creates a new <code>AbstractStateObject</code>.
     *
     * @param parent The parent of this state object, which cannot be <code>null</code>
     * @exception NullPointerException The given parent cannot be <code>null</code>, unless {@link
     * #changeSupport} is overridden and does not throw the exception
     */
    protected AbstractStateObject(StateObject parent) {
        super();
        this.parent = checkParent(parent);
        initialize();
    }

    /**
     * The given {@link StateObjectVisitor} needs to visit this class but it is defined by a
     * third-party provider. This method will programmatically invoke the <b>visit</b> method defined
     * on the given visitor which signature should be.
     *
     * <div><code>{public|protected|private} void visit(ThirdPartyStateObject stateObject)</code></div>
     * <p>
     * or
     *
     * <div><p><code>{public|protected|private} void visit(StateObject stateObject)</code></p></div>
     *
     * @param visitor The {@link StateObjectVisitor} to visit this {@link StateObject} programmatically
     * @return <code>true</code> if the call was successfully executed; <code>false</code> otherwise
     * @since 2.4
     */
    protected boolean acceptUnknownVisitor(StateObjectVisitor visitor) {
        try {
            try {
                acceptUnknownVisitor(visitor, visitor.getClass(), getClass());
            }
            catch (NoSuchMethodException e) {
                // Try with Expression has the parameter type
                acceptUnknownVisitor(visitor, visitor.getClass(), StateObject.class);
            }
            return true;
        }
        catch (NoSuchMethodException e) {
            // Ignore, just do nothing
            return false;
        }
        catch (IllegalAccessException e) {
            // Ignore, just do nothing
            return false;
        }
        catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            RuntimeException actual;
            if (cause instanceof RuntimeException) {
                actual = (RuntimeException) cause;
            }
            else {
                actual = new RuntimeException(cause);
            }
            throw actual;
        }
    }

    /**
     * The given {@link StateObjectVisitor} needs to visit this class but it is defined by a
     * third-party provider. This method will programmatically invoke the <b>visit</b> method defined
     * on the given visitor which signature should be.
     *
     * <div><p><code>{public|protected|private} void visit(ThirdPartyStateObject stateObject)</code></p></div>
     * or
     *
     * <div><p><code>{public|protected|private} void visit(StateObject stateObject)</code></p></div>
     *
     * @param visitor The {@link StateObjectVisitor} to visit this {@link StateObject} programmatically
     * @param type The type found in the hierarchy of the given {@link StateObjectVisitor} that will
     * be used to retrieve the visit method
     * @param parameterType The parameter type of the visit method
     * @see #acceptUnknownVisitor(StateObjectVisitor)
     * @since 2.4
     */
    protected void acceptUnknownVisitor(StateObjectVisitor visitor,
                                        Class<?> type,
                                        Class<?> parameterType) throws NoSuchMethodException,
                                                                       IllegalAccessException,
                                                                       InvocationTargetException{

        try {
            Method visitMethod = type.getDeclaredMethod("visit", parameterType);
            visitMethod.setAccessible(true);
            visitMethod.invoke(visitor, this);
        }
        catch (NoSuchMethodException e) {
            type = type.getSuperclass();
            if (type == Object.class) {
                throw e;
            }
            else {
                acceptUnknownVisitor(visitor, type, parameterType);
            }
        }
    }

    /**
     * Adds the children of this {@link StateObject} to the given list.
     *
     * @param children The list used to store the children
     */
    protected void addChildren(List<StateObject> children) {
    }

    /**
     * Adds to the given list the problems that were found with the current state of this {@link
     * StateObject}, which means there are validation issues.
     *
     * @param problems The list to which the problems are added
     */
    protected void addProblems(List<Problem> problems) {
    }

    @Override
    public final void addPropertyChangeListener(String propertyName, IPropertyChangeListener<?> listener) {
        changeSupport.addPropertyChangeListener(propertyName, listener);
    }

    /**
     * Determines whether the given two {@link StateObject} are equivalent, i.e. the information of
     * both {@link StateObject} is the same.
     *
     * @param stateObject1 The first {@link StateObject} to compare its content with the other one
     * @param stateObject2 The second {@link StateObject} to compare its content with the other one
     * @return <code>true</code> if both objects are equivalent; <code>false</code> otherwise
     */
    protected final boolean areEquivalent(StateObject stateObject1, StateObject stateObject2) {

        // Both are equal or both are null
        if ((stateObject1 == stateObject2) || (stateObject1 == null) && (stateObject2 == null)) {
            return true;
        }

        // One is null but the other is not
        if ((stateObject1 == null) || (stateObject2 == null)) {
            return false;
        }

        return stateObject1.isEquivalent(stateObject2);
    }

    /**
     * Creates a new {@link Problem} describing a single issue found with the information contained
     * in this {@link StateObject}.
     *
     * @param messageKey The key used to retrieve the localized message describing the problem found
     * with the current state of this {@link StateObject}
     * @return The new {@link Problem}
     */
    protected final Problem buildProblem(String messageKey) {
        return buildProblem(messageKey, ExpressionTools.EMPTY_STRING_ARRAY);
    }

    /**
     * Creates a new {@link Problem} describing a single issue found with the information contained
     * in this {@link StateObject}.
     *
     * @param messageKey The key used to retrieve the localized message describing the problem found
     * with the current state of this {@link StateObject}
     * @param arguments A list of arguments that can be used to complete the message or an empty list
     * if no additional information is necessary
     * @return The new {@link Problem}
     */
    protected final Problem buildProblem(String messageKey , String... arguments) {
        return new DefaultProblem(this, messageKey, arguments);
    }

    /**
     * Parses the given JPQL fragment using the given JPQL query BNF.
     *
     * @param jpqlFragment A portion of a JPQL query that will be parsed and converted into a {@link
     * StateObject}
     * @param queryBNFId The unique identifier of the BNF that determines how to parse the fragment
     * @return A {@link StateObject} representation of the given JPQL fragment
     */
    @SuppressWarnings("unchecked")
    protected <T extends StateObject> T buildStateObject(CharSequence jpqlFragment, String queryBNFId) {
        return (T) getQueryBuilder().buildStateObject(this, jpqlFragment, queryBNFId);
    }

    /**
     * Parses the given JPQL fragment using the given JPQL query BNF.
     *
     * @param jpqlFragment A portion of a JPQL query that will be parsed and converted into either a
     * single {@link StateObject} or a list of {@link StateObject}, which happens when the fragment
     * contains a collection of items separated by either a comma or a space
     * @param queryBNFId The unique identifier of the BNF that will be used to parse the fragment
     * @return A list of {@link StateObject StateObjects} representing the given JPQL fragment, which
     * means the list may contain a single {@link StateObject} or a multiple {@link StateObject
     * StateObjects} if the fragment contains more than one expression of the same type. Example:
     * "JOIN e.employees e LEFT JOIN e.address a", this would be parsed in two state objects
     */
    @SuppressWarnings("unchecked")
    protected <T extends StateObject> List<T> buildStateObjects(CharSequence jpqlFragment,
                                                                String queryBNFId) {

        VirtualJPQLQueryBNF queryBNF = new VirtualJPQLQueryBNF(getGrammar());
        queryBNF.setHandleCollection(true);
        queryBNF.setFallbackBNFId(queryBNFId);
        queryBNF.registerQueryBNF(queryBNFId);

        final List<StateObject> items = new ArrayList<StateObject>();

        try {
            StateObject stateObject = buildStateObject(jpqlFragment, queryBNF.getId());

            StateObjectVisitor visitor = new AnonymousStateObjectVisitor() {
                @SuppressWarnings("unused")
                public void visit(CollectionExpressionStateObject stateObject) {
                    CollectionTools.addAll(items, stateObject.children());
                }
                @Override
                protected void visit(StateObject stateObject) {
                    items.add(stateObject);
                }
            };

            stateObject.accept(visitor);
        }
        finally {
            queryBNF.dispose();
        }

        return (List<T>) items;
    }

    /**
     * Checks whether the given parent is <code>null</code> or not. If it's <code>null</code> then
     * throw a {@link NullPointerException}.
     *
     * @param parent The parent of this state object
     * @return The given object
     */
    protected StateObject checkParent(StateObject parent) {
        Assert.isNotNull(parent, "The parent cannot be null");
        return parent;
    }

    @Override
    public final Iterable<StateObject> children() {
        List<StateObject> children = new ArrayList<StateObject>();
        addChildren(children);
        return new SnapshotCloneIterable<StateObject>(children);
    }

    @Override
    public void decorate(StateObject decorator) {
        this.decorator = parent(decorator);
    }

    @Override
    public final boolean equals(Object object) {
        return super.equals(object);
    }

    @Override
    public IdentificationVariableStateObject findIdentificationVariable(String identificationVariable) {
        return parent.findIdentificationVariable(identificationVariable);
    }

    /**
     * Notifies the {@link IPropertyChangeListener IPropertyChangeListeners} that have been registered
     * with the given property name that the property has changed.
     *
     * @param propertyName The name of the property associated with the property change
     * @param oldValue The old value of the property that changed
     * @param newValue The new value of the property that changed
     */
    protected final void firePropertyChanged(String propertyName, Object oldValue, Object newValue) {
        changeSupport.firePropertyChanged(propertyName, oldValue, newValue);
    }

    /**
     * Returns the object responsible to actually register the listeners and to notify them upon
     * changes made to this {@link StateObject}.
     *
     * @return The manager of listeners and notification
     */
    protected final ChangeSupport getChangeSupport() {
        return changeSupport;
    }

    @Override
    public DeclarationStateObject getDeclaration() {
        return parent.getDeclaration();
    }

    @Override
    public StateObject getDecorator() {
        return decorator;
    }

    @Override
    public Expression getExpression() {
        return expression;
    }

    @Override
    public JPQLGrammar getGrammar() {
        return getRoot().getGrammar();
    }

    @Override
    public IManagedTypeProvider getManagedTypeProvider() {
        return getRoot().getManagedTypeProvider();
    }

    @Override
    public StateObject getParent() {
        return parent;
    }

    @Override
    public IJPQLQueryBuilder getQueryBuilder() {
        return getRoot().getQueryBuilder();
    }

    @Override
    public JPQLQueryStateObject getRoot() {
        return parent.getRoot();
    }

    /**
     * Retrieves the external type for the given Java type.
     *
     * @param type The Java type to wrap with an external form
     * @return The external form of the given type
     */
    public IType getType(Class<?> type) {
        return getTypeRepository().getType(type);
    }

    /**
     * Retrieves the external class for the given fully qualified class name.
     *
     * @param typeName The fully qualified class name of the class to retrieve
     * @return The external form of the class to retrieve
     */
    public IType getType(String typeName) {
        return getTypeRepository().getType(typeName);
    }

    /**
     * Returns a helper that gives access to the most common {@link IType types}.
     *
     * @return A helper containing a collection of methods related to {@link IType}
     */
    public TypeHelper getTypeHelper() {
        return getTypeRepository().getTypeHelper();
    }

    /**
     * Returns the type repository for the application.
     *
     * @return The repository of {@link IType ITypes}
     */
    public ITypeRepository getTypeRepository() {
        return getManagedTypeProvider().getTypeRepository();
    }

    @Override
    public final int hashCode() {
        return super.hashCode();
    }

    /**
     * Initializes this state object.
     */
    protected void initialize() {
        changeSupport = new ChangeSupport(this);
    }

    @Override
    public boolean isDecorated() {
        return decorator != null;
    }

    @Override
    public boolean isEquivalent(StateObject stateObject) {
        return (this == stateObject) ||
               ((stateObject != null) && (stateObject.getClass() == getClass()));
    }

    /**
     * Makes sure the given list of {@link StateObject} has this one as its parent.
     *
     * @param stateObjects The list of {@link StateObject} to have this one as its parent
     * @return The given list of {@link StateObject}
     */
    protected <T extends StateObject> List<T> parent(List<T> stateObjects) {
        for (StateObject stateObject : stateObjects) {
            parent(stateObject);
        }
        return stateObjects;
    }

    /**
     * Makes sure the given list of {@link StateObject} has this one as its parent.
     *
     * @param stateObjects The list of {@link StateObject} to have this one as its parent
     * @return The given list of {@link StateObject}
     */
    protected <T extends StateObject> T[] parent(T... stateObjects) {
        for (StateObject stateObject : stateObjects) {
            parent(stateObject);
        }
        return stateObjects;
    }

    /**
     * Makes sure the given {@link StateObject} has this one as its parent.
     *
     * @param stateObject The {@link StateObject} to have this one as its parent
     * @return The given {@link StateObject}
     */
    protected <T extends StateObject> T parent(T stateObject) {
        if (stateObject != null) {
            stateObject.setParent(this);
        }
        return stateObject;
    }

    @Override
    public final void removePropertyChangeListener(String propertyName, IPropertyChangeListener<?> listener) {
        changeSupport.removePropertyChangeListener(propertyName, listener);
    }

    /**
     * Sets the actual parsed object if this {@link StateObject} representation of the JPQL query
     * is created by converting the parsed representation of the JPQL query.
     *
     * @param expression The parsed object when a JPQL query is parsed
     */
    public void setExpression(Expression expression) {
        this.expression = expression;
    }

    @Override
    public final void setParent(StateObject parent) {
        Assert.isNotNull(parent, "The parent cannot be null");
        this.parent = parent;
    }

    @Override
    public final String toString() {
        StringBuilder sb = new StringBuilder();
        toString(sb);
        return sb.toString();
    }

    @Override
    public final void toString(Appendable writer) {
        try {
            toStringInternal(writer);
        }
        catch (IOException e) {
            // Never happens because the Appendable should be an AbstractStringBuilder
        }
    }

    /**
     * Prints out a string representation of this {@link StateObject}.
     * <p>
     * <b>Important:</b> If this {@link StateObject} is decorated by another one, then {@link
     * #toString(Appendable)} from that decorator is invoked, otherwise {@link #toTextInternal(Appendable)}
     * from this one is invoked.
     *
     * @param writer The writer used to print out the string representation
     * @throws IOException This should never happens, it is only required because
     * {@link Appendable#append(CharSequence)} throws an {@link IOException}
     */
    protected final void toStringInternal(Appendable writer) throws IOException {
        if (isDecorated()) {
            getDecorator().toString(writer);
        }
        else {
            toTextInternal(writer);
        }
    }

    protected void toStringItems(Appendable writer,
                                 List<? extends StateObject> items,
                                 boolean useComma) throws IOException {

        int count = items.size();
        int index = -1;

        for (StateObject stateObject : items) {
            stateObject.toString(writer);

            if (++index + 1 < count) {
                if (useComma) {
                    writer.append(COMMA);
                }
                writer.append(SPACE);
            }
        }
    }

    @Override
    public final void toText(Appendable writer) {
        try {
            toTextInternal(writer);
        }
        catch (IOException e) {
            // Never happens because the Appendable should be an AbstractStringBuilder
        }
    }

    /**
     * Prints out a string representation of this {@link StateObject}, which should not be used to
     * define a <code>true</code> string representation of a JPQL query but should be used for
     * debugging purposes.
     *
     * @param writer The writer used to print out the string representation
     * @throws IOException This should never happens, it is only required because {@link Appendable}
     * is used instead of any concrete class
     */
    protected abstract void toTextInternal(Appendable writer) throws IOException;
}
