/*
 * Copyright (c) 2011, 2020 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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.persistence.jpa.jpql.Assert;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.tools.model.IListChangeEvent;
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.IPropertyChangeListener;
import org.eclipse.persistence.jpa.jpql.tools.model.ListChangeEvent;
import org.eclipse.persistence.jpa.jpql.tools.model.PropertyChangeEvent;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.SnapshotCloneListIterable;

/**
 * This <code>ChangeSupport</code> is responsible to notifies registered listeners upon changes made
 * to a {@link StateObject}, those changes are either a property has changed ({@link IPropertyChangeListener})
 * or the content of a list has changed ({@link IListChangeListener}).
 *
 * @version 2.4
 * @since 2.4
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public class ChangeSupport {

    /**
     * The list of registered {@link IListChangeListener listeners}.
     */
    private Map<String, List<IListChangeListener<?>>> listChangeListeners;

    /**
     * The list of registered {@link IPropertyChangeListener listeners}.
     */
    private Map<String, List<IPropertyChangeListener<?>>> propertyChangeListeners;

    /**
     * The object for which this object will take care of notifying the listeners upon changes made
     * to the object's internal state.
     */
    private StateObject source;

    /**
     * Creates a new <code>ChangeSupport</code>.
     *
     * @param source The object for which this object will take care of notifying the listeners upon
     * changes made to the object's internal state
     * @exception NullPointerException The source {@link StateObject} cannot be <code>null</code>
     */
    public ChangeSupport(StateObject source) {
        super();
        initialize(source);
    }

    /**
     * Adds the given item as a child to the given list.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param items The list of  to which the child is added
     * @param listName The name associated with the list
     * @param item The child to become a child of this one
     * @param <T> The type of the items
     */
    public <T> void addItem(ListHolderStateObject<T> source,
                            List<T> items,
                            String listName,
                            T item) {

        addItems(source, items, listName, Collections.singletonList(item));
    }

    /**
     * Adds the given items as children to the given list.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param list The list of items to which the child is added
     * @param listName The name associated with the list
     * @param items The child to become children of this one
     * @param <T> The type of the items
     */
    public <T> void addItems(ListHolderStateObject<T> source,
                             List<T> list,
                             String listName,
                             List<? extends T> items) {

        List<T> original = new ArrayList<T>(list);
        int index = list.size();
        list.addAll(index, items);

        if (hasListChangeListeners(listName)) {

            IListChangeEvent<T> event = new ListChangeEvent<T>(
                source,
                original,
                EventType.ADDED,
                listName,
                new ArrayList<T>(items),
                index,
                index
            );

            fireListChangeEvent(event);
        }
    }

    /**
     * Registers the given {@link IListChangeListener} for the specified list. The listener will be
     * notified only when items are added, removed, moved from the list.
     *
     * @param listName The name of the list for which the listener will be notified when the content
     * of the list has changed
     * @param listener The listener to be notified upon changes
     * @exception NullPointerException {@link IListChangeListener} cannot be <code>null</code>
     * @exception IllegalArgumentException The listener is already registered with the list name
     */
    public void addListChangeListener(String listName, IListChangeListener<?> listener) {
        addListener(listChangeListeners, IListChangeListener.class, listName, listener);
    }

    /**
     * Registers the given list for the specified name. The listener will be notified upon changes.
     *
     * @param listeners The list of listeners from which the given listener is added
     * @param listenerType The type of the listener, which is only used in the exception's message
     * @param name The name of the event for which the listener is registered
     * @param listener The listener to register
     * @exception NullPointerException {@link IPropertyChangeListener} cannot be <code>null</code>
     * @exception IllegalArgumentException The listener is already registered with the given name
     */
    protected <T> void addListener(Map<String, List<T>> listeners,
                                   Class<?> listenerType,
                                   String name,
                                   T listener) {

        if (listener == null) {
            throw new NullPointerException(listenerType.getSimpleName() + " cannot be null");
        }

        List<T> listenerList = listeners.get(name);

        if (listenerList == null) {
            listenerList = new ArrayList<T>();
            listeners.put(name, listenerList);
        }

        if (listenerList.contains(listener)) {
            throw new IllegalArgumentException(listenerType.getSimpleName() + " is already registered");
        }

        listenerList.add(listener);
    }

    /**
     * Registers the given {@link IPropertyChangeListener} for the specified property. The listener
     * will be notified only for changes to the specified property.
     *
     * @param propertyName The name of the property for which the listener was registered
     * @param listener The listener to be notified upon changes
     * @exception NullPointerException {@link IPropertyChangeListener} cannot be <code>null</code>
     * @exception IllegalArgumentException The listener is already registered with the property name
     */
    public void addPropertyChangeListener(String propertyName, IPropertyChangeListener<?> listener) {
        addListener(propertyChangeListeners, IPropertyChangeListener.class, propertyName, listener);
    }

    /**
     * Determines whether the given item can be moved down by one position in the list owned by its
     * parent.
     *
     * @param list The list used to determine if the given item can be moved down in that list
     * @param stateObject The item that could potentially be moved down
     * @return <code>true</code> if the object can be moved down by one unit; <code>false</code>
     * otherwise
     */
    public <T> boolean canMoveDown(List<T> list, T stateObject) {
        int index = list.indexOf(stateObject);
        return (index > -1) && (index + 1 < list.size());
    }

    /**
     * Determines whether the given item can be moved up by one position in the list owned by its
     * parent.
     *
     * @param list The list used to determine if the given item can be moved up in that list
     * @param item The item that could potentially be moved up
     * @return <code>true</code> if the object can be moved up by one unit; <code>false</code>
     * otherwise
     */
    public <T> boolean canMoveUp(List<T> list, T item) {
        int index = list.indexOf(item);
        return (index > 0);
    }

    protected <T> void fireListChangeEvent(IListChangeEvent<T> event) {

        for (IListChangeListener<T> listener : this.<T>listChangeListeners(event.getListName())) {
            try {
                listener.itemsRemoved(event);
            }
            catch (Exception e) {
                // TODO: Log event
            }
        }
    }

    /**
     * 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
     */
    @SuppressWarnings("unchecked")
    public void firePropertyChanged(String propertyName, Object oldValue, Object newValue) {

        if (ExpressionTools.valuesAreDifferent(oldValue, newValue) &&
            hasPropertyChangeListeners(propertyName)) {

            PropertyChangeEvent<Object> event = new PropertyChangeEvent<Object>(source, propertyName, oldValue, newValue);

            for (IPropertyChangeListener<?> listener : propertyChangeListeners(propertyName)) {
                try {
                    ((IPropertyChangeListener<Object>) listener).propertyChanged(event);
                }
                catch (Exception e) {
                    // TODO: Log event
                }
            }
        }
    }

    /**
     * Determines whether there are at least one {@link IListChangeListener} registered to listen for
     * changes made to the list with the given list name.
     *
     * @param listName The name of the list to check if it has registered listeners
     * @return <code>true</code> if listeners have been registered for the given list name;
     * <code>false</code> otherwise
     */
    public boolean hasListChangeListeners(String listName) {
        return hasListeners(listChangeListeners, listName);
    }

    /**
     * Determines whether there are at least one listener registered.
     *
     * @param name The name of the property or list to check if it has registered listeners
     * @return <code>true</code> if listeners have been registered for the given name;
     *  <code>false</code> otherwise
     */
    protected boolean hasListeners(Map<String, ?> listeners, String name) {
        return listeners.containsKey(name);
    }

    /**
     * Determines whether there are at least one {@link IPropertyChangeListener} registered to listen
     * for changes made to the property with the given property name.
     *
     * @param propertyName The name of the property to check if it has registered listeners
     * @return <code>true</code> if listeners have been registered for the given property name;
     * <code>false</code> otherwise
     */
    public boolean hasPropertyChangeListeners(String propertyName) {
        return hasListeners(propertyChangeListeners, propertyName);
    }

    /**
     * Initializes this <code>ChangeSupport</code>.
     *
     * @param source The object for which this object will take care of notifying the listeners upon
     * changes made to the object's internal state
     * @exception NullPointerException The source {@link StateObject} cannot be <code>null</code>
     */
    protected void initialize(StateObject source) {

        Assert.isNotNull(source, "The source StateObject cannot be null");

        this.source                  = source;
        this.listChangeListeners     = new HashMap<String, List<IListChangeListener<?>>>();
        this.propertyChangeListeners = new HashMap<String, List<IPropertyChangeListener<?>>>();
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    protected <T> ListIterable<IListChangeListener<T>> listChangeListeners(String listName) {
        return new SnapshotCloneListIterable(listChangeListeners.get(listName));
    }

    /**
     * Moves the given {@link StateObject} down by one position in the list owned by its parent.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param items The list of items to which the child is moved down
     * @param listName The name associated with the list
     * @param item The child to move down within the list
     * @param <T> The type of the items
     */
    public <T> void moveDown(ListHolderStateObject<T> source,
                             List<T> items,
                             String listName,
                             T item) {

        int index = items.indexOf(item);
        moveItem(source, items, EventType.MOVED_DOWN, listName, item, index + 1, index);
    }

    /**
     * Moves the given item from its current position to a new position in the list owned by its parent.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param items The list of items to which the child is moved
     * @param eventType The type describing how the item was moved (up or down)
     * @param listName The name associated with the list
     * @param item The child to move within the list
     * @param oldIndex The current position of the item to move
     * @param newIndex The new position within the list
     * @param <T> The type of the items
     */
    protected <T> void moveItem(ListHolderStateObject<T> source,
                                List<T> items,
                                EventType eventType,
                                String listName,
                                T item,
                                int oldIndex,
                                int newIndex) {

        List<T> original = new ArrayList<T>(items);
        items.remove(oldIndex);
        items.add(newIndex, item);

        if (hasListChangeListeners(listName)) {

            IListChangeEvent<T> event = new ListChangeEvent<T>(
                source,
                original,
                eventType,
                listName,
                Collections.singletonList(item),
                newIndex,
                oldIndex
            );

            fireListChangeEvent(event);
        }
    }

    /**
     * Moves the given item up by one position in the list owned by its parent.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param items The list of items to which the child is moved up
     * @param listName The name associated with the list
     * @param item The child to move up within the list
     * @param <T> The type of the items
     */
    public <T> void moveUp(ListHolderStateObject<T> source,
                           List<T> items,
                           String listName,
                           T item) {

        int index = items.indexOf(item);
        moveItem(source, items, EventType.MOVED_DOWN, listName, item, index - 1, index);
    }

    protected ListIterable<IPropertyChangeListener<?>> propertyChangeListeners(String propertyName) {
        return new SnapshotCloneListIterable<IPropertyChangeListener<?>>(
            propertyChangeListeners.get(propertyName)
        );
    }

    /**
     * Removes the given item from the list of children.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param items The list of item to which the child is removed
     * @param listName The name associated with the list
     * @param item The child to removed from the list
     * @param <T> The type of the items
     */
    public <T> void removeItem(ListHolderStateObject<T> source,
                               List<T> items,
                               String listName,
                               T item) {

        List<T> original = new ArrayList<T>(items);
        int index = items.indexOf(item);
        items.remove(index);

        if (hasListChangeListeners(listName)) {

            IListChangeEvent<T> event = new ListChangeEvent<T>(
                source,
                original,
                EventType.REMOVED,
                listName,
                Collections.singletonList(item),
                index,
                index
            );

            fireListChangeEvent(event);
        }
    }

    /**
     * Removes the given items from the list of children.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param list The list of items to which the child is removed
     * @param listName The name associated with the list
     * @param items The items to removed from the list
     * @param <T> The type of the items
     */
    public <T> void removeItems(ListHolderStateObject<T> source,
                                List<? extends T> list,
                                String listName,
                                Collection<? extends T> items) {

        List<T> original = new ArrayList<T>(list);
        list.removeAll(items);

        if (hasListChangeListeners(listName)) {

            IListChangeEvent<T> event = new ListChangeEvent<T>(
                source,
                original,
                EventType.REMOVED,
                listName,
                new ArrayList<T>(items),
                -1,
                -1
            );

            fireListChangeEvent(event);
        }
    }

    /**
     * Unregisters the given {@link IListChangeListener} that was registered for the specified list.
     * The listener will no longer be notified only when items are added, removed, moved from the
     * list.
     *
     * @param listName The name of the list for which the listener was registered
     * @param listener The listener to unregister
     * @exception NullPointerException {@link IListChangeListener} cannot be <code>null</code>
     * @exception IllegalArgumentException The listener was never registered with the list name
     */
    public void removeListChangeListener(String listName, IListChangeListener<?> listener) {
        removeListener(listChangeListeners, IListChangeListener.class, listName, listener);
    }

    /**
     * Unregisters the given listener that was registered for the specified name. The listener will
     * no longer be notified upon changes.
     *
     * @param listeners The list of listeners from which the given listener is removed
     * @param listenerType The type of the listener, which is only used in the exception's message
     * @param name The name of the event for which the listener was registered
     * @param listener The listener to unregister
     * @exception NullPointerException {@link IPropertyChangeListener} cannot be <code>null</code>
     * @exception IllegalArgumentException The listener was never registered with the given name
     */
    protected <T> void removeListener(Map<String, List<T>> listeners,
                                      Class<?> listenerType,
                                      String name,
                                      T listener) {

        if (listener == null) {
            throw new NullPointerException(listenerType.getSimpleName() + " cannot be null");
        }

        List<T> listenerList = listeners.get(name);

        if (listenerList == null) {
            throw new IllegalArgumentException("No listeners were registered for " + name);
        }

        if (!listenerList.remove(listener)) {
            throw new IllegalArgumentException(listenerType.getSimpleName() + " was never registered");
        }

        if (listeners.isEmpty()) {
            listeners.remove(name);
        }
    }

    /**
     * Unregisters the given {@link IPropertyChangeListener} that was registered for the specified
     * property. The listener will no longer be notified when the property changes.
     *
     * @param propertyName The name of the property for which the listener was registered
     * @param listener The listener to unregister
     * @exception NullPointerException {@link IPropertyChangeListener} cannot be <code>null</code>
     * @exception IllegalArgumentException The listener was never registered with the property name
     */
    public void removePropertyChangeListener(String propertyName, IPropertyChangeListener<?> listener) {
        removeListener(propertyChangeListeners, IPropertyChangeListener.class, propertyName, listener);
    }

    /**
     * Replaces the item at the given position by a new one.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param items The list of items to which a child is replaced
     * @param listName The name associated with the list
     * @param index The position of the item to replace
     * @param item The item to replace the one at the given position
     * @param <T> The type of the items
     */
    public <T> void replaceItem(ListHolderStateObject<T> source,
                                List<T> items,
                                String listName,
                                int index,
                                T item) {

        List<T> original = new ArrayList<T>(items);
        items.set(index, item);

        if (hasListChangeListeners(listName)) {

            IListChangeEvent<T> event = new ListChangeEvent<T>(
                source,
                original,
                EventType.REPLACED,
                listName,
                items,
                index,
                index
            );

            fireListChangeEvent(event);
        }
    }

    /**
     * Replaces the given list by removing any existing items and adding the items contained in the
     * second list.
     *
     * @param source The {@link ListHolderStateObject} from where the change is coming
     * @param items The list of items to which the child is removed
     * @param listName The name associated with the list
     * @param newItems The items to removed from the list
     * @param <T> The type of the items
     */
    public <T> void replaceItems(ListHolderStateObject<T> source,
                                List<T> items,
                                String listName,
                                List<T> newItems) {

        List<T> original = new ArrayList<T>(items);
        items.clear();
        items.addAll(newItems);

        if (hasListChangeListeners(listName)) {

            IListChangeEvent<T> event = new ListChangeEvent<T>(
                source,
                original,
                EventType.REPLACED,
                listName,
                items,
                -1,
                -1
            );

            fireListChangeEvent(event);
        }
    }
}
