/*
 * 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.Collection;
import java.util.Collections;
import java.util.List;

import org.eclipse.persistence.jpa.jpql.tools.model.IListChangeListener;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.SnapshotCloneListIterable;

/**
 * The abstraction definition of a {@link StateObject} that holds onto a list of children, the
 * methods defined in {@link ListHolderStateObject} are automatically handled here.
 *
 * @version 2.4
 * @since 2.4
 * @author Pascal Filion
 */
public abstract class AbstractListHolderStateObject<T extends StateObject> extends AbstractStateObject
                                                                           implements ListHolderStateObject<T> {

    /**
     * The list of children owned by this one.
     */
    private List<T> items;

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

    /**
     * Creates a new <code>AbstractListHolderStateObject</code>.
     *
     * @param parent The parent of this state object, which cannot be <code>null</code>
     * @param items The list of {@link StateObject StateObjects} to add as children to this one
     * @exception NullPointerException The given parent cannot be <code>null</code>
     */
    protected AbstractListHolderStateObject(StateObject parent, List<? extends T> items) {
        super(parent);
        this.items = new ArrayList<>(items);
        parent(items);
    }

    /**
     * Creates a new <code>AbstractListHolderStateObject</code>.
     *
     * @param parent The parent of this state object, which cannot be <code>null</code>
     * @param items The list of {@link StateObject StateObjects} to add as children to this one
     * @exception NullPointerException The given parent cannot be <code>null</code>
     */
    @SafeVarargs
    @SuppressWarnings({"varargs"})
    protected AbstractListHolderStateObject(StateObject parent, T... items) {
        super(parent);
        this.items = new ArrayList<>();
        Collections.addAll(this.items, parent(items));
    }

    @Override
    protected void addChildren(List<StateObject> children) {
        super.addChildren(children);
        children.addAll(items);
    }

    @Override
    public <S extends T> S addItem(S item) {
        getChangeSupport().addItem(this, this.items, listName(), parent(item));
        return item;
    }

    @Override
    public void addItems(List<? extends T> items) {
        getChangeSupport().addItems(this, this.items, listName(), parent(items));
    }

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

    /**
     * Determines whether the children of this {@link StateObject} are equivalent to the children
     * of the given one, i.e. the information of the {@link StateObject StateObjects} is the same.
     *
     * @param stateObject The {@link StateObject} to compare its children to this one's children
     * @return <code>true</code> if both have equivalent children; <code>false</code> otherwise
     */
    protected boolean areChildrenEquivalent(AbstractListHolderStateObject<? extends StateObject> stateObject) {

        int size = itemsSize();

        if (size != stateObject.itemsSize()) {
            return false;
        }

        for (int index = size; --index >= 0; ) {

            StateObject child1 = getItem(index);
            StateObject child2 = stateObject.getItem(index);

            if (!child1.isEquivalent(child2)) {
                return false;
            }
        }

        return true;
    }

    @Override
    public boolean canMoveDown(T stateObject) {
        return getChangeSupport().canMoveDown(items, stateObject);
    }

    @Override
    public boolean canMoveUp(T stateObject) {
        return getChangeSupport().canMoveUp(items, stateObject);
    }

    @Override
    public T getItem(int index) {
        return items.get(index);
    }

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

    @Override
    protected void initialize() {
        super.initialize();
        items = new ArrayList<>();
    }

    @Override
    public ListIterable<? extends T> items() {
        return new SnapshotCloneListIterable<>(items);
    }

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

    /**
     * Returns the name that is uniquely identifying the list.
     *
     * @return The unique name identifying the list
     */
    protected abstract String listName();

    @Override
    public T moveDown(T item) {
        getChangeSupport().moveDown(this, items, listName(), item);
        return item;
    }

    @Override
    public T moveUp(T item) {
        getChangeSupport().moveUp(this, items, listName(), item);
        return item;
    }

    @Override
    public void removeItem(T stateObject) {
        getChangeSupport().removeItem(this, items, listName(), stateObject);
    }

    @Override
    public void removeItems(Collection<T> items) {
        getChangeSupport().removeItems(this, this.items, listName(), items);
    }

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

    /**
     * Adds to the given writer a crude string representation of the children of this one.
     *
     * @param writer The writer used to print out the string representation
     * @param useComma Determines whether a comma should be added after each item, except after the
     * last one
     * @throws IOException This should never happens, only required because {@link Appendable} is
     * used instead of {@link StringBuilder} for instance
     */
    protected void toStringItems(Appendable writer, boolean useComma) throws IOException {
        toStringItems(writer, items, useComma);
    }
}
