/*
 * 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 java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.StringTokenizer;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.parser.AbstractPathExpression;
import org.eclipse.persistence.jpa.jpql.parser.IdentificationVariableBNF;
import org.eclipse.persistence.jpa.jpql.tools.model.IListChangeEvent.EventType;
import org.eclipse.persistence.jpa.jpql.tools.model.IListChangeListener;
import org.eclipse.persistence.jpa.jpql.tools.model.ListChangeEvent;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedType;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedTypeProvider;
import org.eclipse.persistence.jpa.jpql.tools.spi.IMapping;
import org.eclipse.persistence.jpa.jpql.tools.spi.IType;
import org.eclipse.persistence.jpa.jpql.tools.spi.ITypeDeclaration;
import org.eclipse.persistence.jpa.jpql.utility.CollectionTools;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.SnapshotCloneListIterable;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.*;

/**
 * An identification variable followed by the navigation operator (.) and a state field or
 * association field is a path expression. The type of the path expression is the type computed as
 * the result of navigation; that is, the type of the state field or association field to which the
 * expression navigates.
 *
 * @see AbstractPathExpression
 *
 * @version 2.5
 * @since 2.4
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public abstract class AbstractPathExpressionStateObject extends AbstractStateObject
                                                        implements ListHolderStateObject<String> {

    /**
     * The {@link StateObject} that represents the identification variable portion of the path
     * expression, which can be one of the following when the JPA version is 2.0 or later:
     * <ul>
     * <li>{@link IdentificationVariableStateObject}</li>
     * <li>{@link KeyExpressionStateObject}</li>
     * <li>{@link ValueExpressionStateObject}</li>
     * </ul>
     */
    private StateObject identificationVariable;

    /**
     *
     */
    private IManagedType managedType;

    /**
     *
     */
    private ArrayList<IMapping> mappings;

    /**
     * The list of segments, including the general identification variable.
     */
    private List<String> paths;

    /**
     *
     */
    private boolean resolved;

    /**
     * The {@link IType} of the object being mapped to this identification variable.
     */
    private IType type;

    /**
     * The {@link ITypeDeclaration} of the object being mapped to this identification variable.
     */
    private ITypeDeclaration typeDeclaration;

    /**
     * Notifies the identification variable property has changed.
     */
    public static final String IDENTIFICATION_VARIABLE_PROPERTY = "identificationVariable";

    /**
     * Notifies the content of the paths list has changed.
     */
    public static final String PATHS_LIST = "paths";

    /**
     * Creates a new <code>AbstractPathExpressionStateObject</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>
     */
    protected AbstractPathExpressionStateObject(StateObject parent) {
        super(parent);
    }

    /**
     * Creates a new <code>AbstractPathExpressionStateObject</code>.
     *
     * @param parent The parent of this state object, which cannot be <code>null</code>
     * @param path The path expression
     * @exception NullPointerException The given parent cannot be <code>null</code>
     */
    protected AbstractPathExpressionStateObject(StateObject parent, String path) {
        super(parent);
        setPath(path);
    }

    @Override
    protected void addChildren(List<StateObject> children) {

        super.addChildren(children);

        StateObject stateObject = getIdentificationVariable();

        if (stateObject != null) {
            children.add(stateObject);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public String addItem(String item) {
        getChangeSupport().addItem(this, paths, PATHS_LIST, item);
        return item;
    }

    @Override
    public void addItems(List<? extends String> items) {
        getChangeSupport().addItems(this, paths, PATHS_LIST, items);
    }

    @Override
    public void addListChangeListener(String listName, IListChangeListener<String> listener) {
        getChangeSupport().addListChangeListener(listName, listener);
    }

    /**
     * Appends the given sequence of characters to the path expression. If the sequence does not
     * begin with a dot, then the first segment will be appended to the last segment and then new
     * segments will be created.
     *
     * @param text The sequence of characters to append to the path expression
     */
    public void append(String text) {

        StringBuilder word = new StringBuilder();
        int pathCount = paths.size();
        boolean appendToLastSegment = true;
        int startIndex = pathCount;

        for (int index = 0, count = text.length(); index < count; index++) {
            char character = text.charAt(index);

            if (character == DOT) {
                if (word.length() > 0) {
                    // Append the content of the buffer to the end of the last segment
                    if (appendToLastSegment) {
                        String currentPath = paths.get(pathCount - 1);
                        paths.set(pathCount - 1, currentPath + word);
                        startIndex = pathCount - 1;
                    }
                    // Add a new segment
                    else {
                        paths.add(word.toString());
                        pathCount++;
                    }

                    // Clear the buffer
                    word.delete(0, word.length());
                }

                appendToLastSegment = false;
                continue;
            }
            // Add the character to the buffer
            else {
                word.append(character);
            }
        }

        if (word.length() > 0) {
            // Append the content of the buffer to the end of the last segment
            if (appendToLastSegment) {
                String currentPath = paths.get(pathCount - 1);
                paths.set(pathCount - 1, currentPath + word);
                startIndex = pathCount - 1;
            }
            // Add a new segment
            else {
                paths.add(word.toString());
            }
        }

        ListChangeEvent<String> event = new ListChangeEvent<String>(this, paths, EventType.CHANGED, PATHS_LIST, paths, startIndex, itemsSize());
        getChangeSupport().fireListChangeEvent(event);
    }

    @Override
    public boolean canMoveDown(String item) {
        return false;
    }

    @Override
    public boolean canMoveUp(String item) {
        return false;
    }

    /**
     * Clears the values related to the managed type and type.
     */
    protected void clearResolvedObjects() {

        mappings.clear();

        resolved        = false;
        type            = null;
        typeDeclaration = null;
    }

    @Override
    public AbstractPathExpression getExpression() {
        return (AbstractPathExpression) super.getExpression();
    }

    /**
     * Returns the {@link StateObject} representing the identification variable that starts the path
     * expression, which can be a sample identification variable, a map value, map key or map entry
     * expression.
     *
     * @return The root of the path expression
     */
    public StateObject getIdentificationVariable() {
        if ((identificationVariable == null) && hasItems()) {
            identificationVariable = buildStateObject(getItem(0), IdentificationVariableBNF.ID);
        }
        return identificationVariable;
    }

    @Override
    public String getItem(int index) {
        return paths.get(index);
    }

    /**
     * Returns
     *
     * @return
     */
    public IManagedType getManagedType() {
        if (managedType == null) {
            managedType = resolveManagedType();
        }
        return managedType;
    }

    /**
     * Returns
     *
     * @return
     */
    public IMapping getMapping() {
        resolveMappings();
        return mappings.get(itemsSize() - 1);
    }

    /**
     * Retrieves the {@link IMapping} for the path at the given position.
     *
     * @param index The index of the path for which its {@link IMapping} should be retrieved, which
     * should start at 1 to skip the identification variable
     */
    public IMapping getMapping(int index) {
        resolveMappings();
        return mappings.get(index);
    }

    /**
     * Returns the string representation of the path expression. If the identification variable is
     * virtual, then it is not part of the result.
     *
     * @return The path expression, which is never <code>null</code>
     */
    public String getPath() {
        return toString();
    }

    /**
     * Returns the {@link IType} of the field handled by this object.
     *
     * @return Either the {@link IType} that was resolved by this state object or the {@link IType}
     * for {@link IType#UNRESOLVABLE_TYPE} if it could not be resolved
     */
    public IType getType() {
        if (type == null) {
            type = resolveType();
        }
        return type;
    }

    /**
     * Returns the {@link ITypeDeclaration} of the field handled by this object.
     *
     * @return Either the {@link ITypeDeclaration} that was resolved by this object or the {@link
     * ITypeDeclaration} for {@link IType#UNRESOLVABLE_TYPE} if it could not be resolved
     */
    public ITypeDeclaration getTypeDeclaration() {
        if (typeDeclaration == null) {
            typeDeclaration = resolveTypeDeclaration();
        }
        return typeDeclaration;
    }

    /**
     * Determines whether the identification variable is present.
     *
     * @return <code>true</code> the identification variable is present; <code>false</code> otherwise
     */
    public boolean hasIdentificationVariable() {
        return getIdentificationVariable() != null;
    }

    @Override
    public boolean hasItems() {
        return !paths.isEmpty();
    }

    @Override
    protected void initialize() {
        super.initialize();
        paths    = new ArrayList<String>();
        mappings = new ArrayList<IMapping>();
    }

    @Override
    public boolean isEquivalent(StateObject stateObject) {

        if (!super.isEquivalent(stateObject)) {
            return false;
        }

        AbstractPathExpressionStateObject path = (AbstractPathExpressionStateObject) stateObject;

        if (!areEquivalent(getIdentificationVariable(), path.getIdentificationVariable())) {
            return false;
        }

        int index = itemsSize();

        if (index != path.itemsSize()) {
            return false;
        }

        // Skip index 0, it is already tested and two identification
        // variables with different case are equivalent
        while (--index > 0) {
            String path1 = getItem(index);
            String path2 = path.getItem(index);

            if (ExpressionTools.valuesAreDifferent(path1, path2)) {
                return false;
            }
        }

        return true;
    }

    @Override
    public ListIterable<String> items() {
        return new SnapshotCloneListIterable<String>(paths);
    }

    @Override
    public int itemsSize() {
        return paths.size();
    }

    @Override
    public String moveDown(String item) {
        throw new RuntimeException(getClass().getName() + " does not support moveDown(String).");
    }

    @Override
    public String moveUp(String item) {
        throw new RuntimeException(getClass().getName() + " does not support moveUp(String).");
    }

    /**
     * Removes the single path at the given index.
     *
     * @param index The position of the single path to remove. If the index is 0, then the
     * identification variable is nullified
     */
    public void removeItem(int index) {
        if (index == 0) {
            setIdentificationVariableInternally(null);
        }
        removeItem(getItem(index));
    }

    @Override
    public void removeItem(String item) {
        getChangeSupport().removeItem(this, paths, PATHS_LIST, item);
    }

    @Override
    public void removeItems(Collection<String> items) {
        getChangeSupport().removeItems(this, this.paths, PATHS_LIST, items);
    }

    @Override
    public void removeListChangeListener(String listName, IListChangeListener<String> listener) {
        getChangeSupport().removeListChangeListener(listName, listener);
    }

    /**
     * Resolves
     *
     * @return
     */
    protected abstract IManagedType resolveManagedType();

    /**
     * Resolves the {@link IMapping} objects that constitutes the path expression.
     */
    protected void resolveMappings() {

        if (!resolved) {
            resolved = true;
            IManagedTypeProvider provider = getManagedTypeProvider();
            IManagedType managedType = null;

            for (int index = 0, count = itemsSize(); index < count; index++) {

                // Identification variable
                if (index == 0) {
                    StateObject stateObject = getIdentificationVariable();

                    // The identification variable is not set, which means the traversal can happen
                    if (stateObject != null) {
                        managedType = getDeclaration().findManagedType(stateObject);
                    }

                    mappings.add(null);
                }
                // Resolve the path expression after the identification variable
                else if (managedType != null) {

                    String path = getItem(index);

                    // Cache the mapping
                    IMapping mapping = managedType.getMappingNamed(path);
                    mappings.add(mapping);

                    // Continue by retrieving the managed type
                    if (mapping != null) {
                        managedType = provider.getManagedType(mapping.getType());
                    }
                    else {
                        managedType = null;
                    }
                }
                else {
                    mappings.add(null);
                }
            }
        }
    }

    /**
     * Resolves the {@link IType} of the property handled by this object.
     *
     * @return Either the {@link IType} that was resolved by this object or the {@link IType} for
     * {@link IType#UNRESOLVABLE_TYPE} if it could not be resolved
     */
    protected abstract IType resolveType();

    /**
     * Resolves the {@link ITypeDeclaration} of the property handled by this object.
     *
     * @return Either the {@link ITypeDeclaration} that was resolved by this object or the {@link
     * ITypeDeclaration} for {@link IType#UNRESOLVABLE_TYPE} if it could not be resolved
     */
    protected ITypeDeclaration resolveTypeDeclaration() {
        resolveMappings();
        return getMapping().getTypeDeclaration();
    }

    /**
     * Sets the {@link StateObject} representing the identification variable that starts the path
     * expression, which can be a sample identification variable, a map value, map key or map entry
     * expression.
     *
     * @param identificationVariable The root of the path expression
     */
    public void setIdentificationVariable(StateObject identificationVariable) {
        setIdentificationVariableInternally(identificationVariable);
        getChangeSupport().replaceItem(this, paths, PATHS_LIST, 0, identificationVariable.toString());
    }

    /**
     * Sets the {@link StateObject} representing the identification variable that starts the path
     * expression, which can be a sample identification variable, a map value, map key or map entry
     * expression. This method does not replace the first path in the list of paths.
     *
     * @param identificationVariable The root of the path expression
     */
    protected void setIdentificationVariableInternally(StateObject identificationVariable) {
        clearResolvedObjects();
        StateObject oldIdentificationVariable = this.identificationVariable;
        this.identificationVariable = parent(identificationVariable);
        firePropertyChanged(IDENTIFICATION_VARIABLE_PROPERTY, oldIdentificationVariable, identificationVariable);
    }

    /**
     * Changes the path expression with the list of segments, the identification variable will also
     * be updated with the first segment.
     *
     * @param path The new path expression
     */
    public void setPath(CharSequence path) {

        List<String> paths = new ArrayList<String>();

        for (StringTokenizer tokenizer = new StringTokenizer(path.toString(), ".", true); tokenizer.hasMoreTokens(); ) {
            String token = tokenizer.nextToken();
            if (!token.equals(".")) {
                paths.add(token);
            }
            else if (!tokenizer.hasMoreTokens()) {
                paths.add(ExpressionTools.EMPTY_STRING);
            }
        }

        setPaths(paths.listIterator());
    }

    /**
     * Replaces the existing path segment to become the given one.
     *
     * @param index The position of the path segment to replace
     * @param path The replacement
     */
    public void setPath(int index, String path) {

        if (index == 0) {
            setIdentificationVariableInternally(null);
        }
        else {
            clearResolvedObjects();
        }

        getChangeSupport().replaceItem(this, paths, PATHS_LIST, index, path);
    }

    /**
     * Changes the path expression with the list of segments, the identification variable will also
     * be updated with the first segment.
     *
     * @param paths The new path expression
     */
    public void setPaths(List<String> paths) {
        setIdentificationVariableInternally(null);
        getChangeSupport().replaceItems(this, this.paths, PATHS_LIST, paths);
    }

    /**
     * Changes the path expression with the list of segments, the identification variable will also
     * be updated with the first segment.
     *
     * @param paths The new path expression
     */
    public void setPaths(ListIterator<String> paths) {
        setPaths(CollectionTools.list(paths));
    }

    /**
     * Changes the path expression with the list of segments, the identification variable will also
     * be updated with the first segment.
     *
     * @param paths The new path expression
     */
    public void setPaths(String... paths) {
        setPaths(Arrays.asList(paths));
    }

    @Override
    protected void toTextInternal(Appendable writer) throws IOException {

        StateObject stateObject = getIdentificationVariable();

        if (stateObject != null) {
            String variable = stateObject.toString();

            if (variable.length() > 0) {
                writer.append(variable);

                if (hasItems()) {
                    writer.append(DOT);
                }
            }
        }

        for (int index = 1, count = paths.size(); index < count; index++) {
            writer.append(paths.get(index));
            if (index < count - 1) {
                writer.append(DOT);
            }
        }
    }
}
