/*
 * 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
//     08/15/2008-1.0.1 Chris Delahunt
//       - 237545: List attribute types on OneToMany using @OrderBy does not work with attribute change tracking
package org.eclipse.persistence.internal.queries;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.ChangeRecord;
import org.eclipse.persistence.internal.sessions.CollectionChangeRecord;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.ReadAllQuery;

/**
 * <p><b>Purpose</b>: A ListContainerPolicy is ContainerPolicy whose container class
 * implements the List interface.  This signifies that the collection has order
 * <p><b>Responsibilities</b>:
 * Provide the functionality to operate on an instance of a List.
 *
 * @see ContainerPolicy
 * @see CollectionContainerPolicy
 */
public class ListContainerPolicy extends CollectionContainerPolicy {
    /**
     * INTERNAL:
     * Construct a new policy.
     */
    public ListContainerPolicy() {
        super();
    }

    /**
     * INTERNAL:
     * Construct a new policy for the specified class.
     */
    public ListContainerPolicy(Class<?> containerClass) {
        super(containerClass);
    }

    /**
     * INTERNAL:
     * Construct a new policy for the specified class name.
     */
    public ListContainerPolicy(String containerClassName) {
        super(containerClassName);
    }

    /**
     * INTERNAL:
     * Returns the element at the specified position in this list.
     * The session may be required to unwrap for the wrapper policy.
     */
    public Object get(int index, Object container, AbstractSession session){
        if ( (index <0) || (index>= sizeFor(container)) ) {
            return null;
        }
        Object object  = ((List)container).get(index);
        if (hasElementDescriptor() && getElementDescriptor().hasWrapperPolicy()) {
            object = getElementDescriptor().getObjectBuilder().unwrapObject(object, session);
        }
        return object;
    }

    /**
     * INTERNAL:
     * Validate the container type.
     */
    @Override
    public boolean isValidContainer(Object container) {
        // PERF: Use instanceof which is inlined, not isAssignable which is very inefficent.
        return container instanceof List;
    }

    /**
     * INTERNAL:
     * Returns true if the collection has order
     *
     * @see ContainerPolicy#iteratorFor(java.lang.Object)
     */
    @Override
    public boolean hasOrder() {
        return true;
    }

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

    /**
     * INTERNAL:
     * Returns the index in this list of the first occurrence of the specified element,
     * or -1 if this list does not contain this element
     * The session may be required to unwrap for the wrapper policy.
     */
    public int indexOf(Object element, Object container, AbstractSession session) {
       if (hasElementDescriptor() && getElementDescriptor().hasWrapperPolicy()) {
           // The wrapper for the object must be removed.
           int count = -1;
           Object iterator = iteratorFor(container);
           while (hasNext(iterator)) {
               count++;
               Object next = next(iterator);
               if (getElementDescriptor().getObjectBuilder().unwrapObject(next, session).equals(element)) {
                   return count;
               }
           }
           return -1;
       } else {
           return ((List)container).indexOf(element);
       }
    }

    /**
     * This method is used to bridge the behavior between Attribute Change Tracking and
     * deferred change tracking with respect to adding the same instance multiple times.
     * Each ContainerPolicy type will implement specific behavior for the collection
     * type it is wrapping.  These methods are only valid for collections containing object references
     */
    @Override
    public void recordAddToCollectionInChangeRecord(ObjectChangeSet changeSetToAdd, CollectionChangeRecord collectionChangeRecord){
        if (collectionChangeRecord.getRemoveObjectList().containsKey(changeSetToAdd)) {
            collectionChangeRecord.getRemoveObjectList().remove(changeSetToAdd);
        } else {
            if (collectionChangeRecord.getAddObjectList().containsKey(changeSetToAdd)){
                collectionChangeRecord.getAddOverFlow().add(changeSetToAdd);
            }else{
                collectionChangeRecord.getAddObjectList().put(changeSetToAdd, changeSetToAdd);
            }
        }
    }

    /**
     * This method is used to bridge the behavior between Attribute Change Tracking and
     * deferred change tracking with respect to adding the same instance multiple times.
     * Each ContainerPolicy type will implement specific behavior for the collection
     * type it is wrapping.  These methods are only valid for collections containing object references
     */
    @Override
    public void recordRemoveFromCollectionInChangeRecord(ObjectChangeSet changeSetToRemove, CollectionChangeRecord collectionChangeRecord){
        if(collectionChangeRecord.getAddObjectList().containsKey(changeSetToRemove)) {
            if (collectionChangeRecord.getAddOverFlow().contains(changeSetToRemove)){
                collectionChangeRecord.getAddOverFlow().remove(changeSetToRemove);
            }else {
                collectionChangeRecord.getAddObjectList().remove(changeSetToRemove);
            }
        } else {
            collectionChangeRecord.getRemoveObjectList().put(changeSetToRemove, changeSetToRemove);
        }
    }

    /**
     * INTERNAL:
     * Update a ChangeRecord to replace the ChangeSet for the old entity with the changeSet for the new Entity.  This is
     * used when an Entity is merged into itself and the Entity reference new or detached entities.
     */
    @Override
    public void updateChangeRecordForSelfMerge(ChangeRecord changeRecord, Object source, Object target, ForeignReferenceMapping mapping, UnitOfWorkChangeSet parentUOWChangeSet, UnitOfWorkImpl unitOfWork){
        Map<ObjectChangeSet, ObjectChangeSet> list = ((CollectionChangeRecord)changeRecord).getAddObjectList();

        ObjectChangeSet sourceSet = parentUOWChangeSet.getCloneToObjectChangeSet().get(source);
        if (list.containsKey(sourceSet)){
            ObjectChangeSet targetSet = ((UnitOfWorkChangeSet)unitOfWork.getUnitOfWorkChangeSet()).findOrCreateLocalObjectChangeSet(target, mapping.getReferenceDescriptor(), unitOfWork.isCloneNewObject(target));
            parentUOWChangeSet.addObjectChangeSetForIdentity(targetSet, target);
            list.remove(sourceSet);
            list.put(targetSet, targetSet);
            return;
        }
        List<ObjectChangeSet> overFlow = ((CollectionChangeRecord)changeRecord).getAddOverFlow();
        int index = 0;
        for (ObjectChangeSet changeSet: overFlow){
            if (changeSet == sourceSet){
                overFlow.set(index,((UnitOfWorkChangeSet)unitOfWork.getUnitOfWorkChangeSet()).findOrCreateLocalObjectChangeSet(target, mapping.getReferenceDescriptor(), unitOfWork.isCloneNewObject(target)));
                return;
            }
            ++index;
        }
    }


    /**
     * INTERNAL:
     * This method is used to load a relationship from a list of PKs. This list
     * may be available if the relationship has been cached.
     */
    @Override
    public Object valueFromPKList(Object[] pks, AbstractRecord foreignKeys, ForeignReferenceMapping mapping, AbstractSession session){

        Object result = containerInstance(pks.length);
        Map<Object, Object> fromCache = session.getIdentityMapAccessorInstance().getAllFromIdentityMapWithEntityPK(pks, elementDescriptor);


        List foreignKeyValues = new ArrayList(pks.length - fromCache.size());
        for (int index = 0; index < pks.length; ++index){
            //it is a map so the keys are in the list but we do not need them in this case
            Object pk = pks[index];
            if (!fromCache.containsKey(pk)){
                if (this.elementDescriptor.getCachePolicy().getCacheKeyType() == CacheKeyType.CACHE_ID){
                    foreignKeyValues.add(Arrays.asList(((CacheId)pk).getPrimaryKey()));
                }else{
                    foreignKeyValues.add(pk);
                }
            }
        }
        if (!foreignKeyValues.isEmpty()){
            if (foreignKeyValues.size() == pks.length){
                //need to find all of the entities so just perform a FK search
                return session.executeQuery(mapping.getSelectionQuery(), foreignKeys);
            }
            ReadAllQuery query = new ReadAllQuery();
            query.setReferenceClass(this.elementDescriptor.getJavaClass());
            query.setIsExecutionClone(true);
            query.setSession(session);
            query.addArgument(ForeignReferenceMapping.QUERY_BATCH_PARAMETER);
            query.setSelectionCriteria(elementDescriptor.buildBatchCriteriaByPK(query.getExpressionBuilder(), query));
            int pkCount = foreignKeyValues.size();
            Collection<Object> temp = new ArrayList<>();
            List arguments = new ArrayList();
            arguments.add(foreignKeyValues);
            if (pkCount > 1000){
                int index = 0;

                while ( index+1000 < pkCount ) { // some databases only support ins < 1000 entries
                    List pkList = new ArrayList();
                    pkList.addAll(foreignKeyValues.subList(index, index+1000));
                    arguments.set(0, pkList);
                    query.setArgumentValues(arguments);
                    temp.addAll((Collection<Object>) session.executeQuery(query));
                    index += 1000;
                }
                foreignKeyValues = foreignKeyValues.subList(index, pkCount);
            }
            arguments.set(0, foreignKeyValues);
            query.setArgumentValues(arguments);
            //need to put the translation row here or it will be replaced later.
            temp.addAll((Collection<Object>) session.executeQuery(query));
            if (temp.size() < pkCount){
                //Not enough results have been found, this must be a stale collection with a removed
                //element.  Execute a reload based on FK.
                return session.executeQuery(mapping.getSelectionQuery(), foreignKeys);
            }
            for (Object element: temp){
                Object pk = elementDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(element, session);
                fromCache.put(pk, element);
            }
        }
        for(Object key : pks){
            addInto(fromCache.get(key), result, session);
        }
        return result;
    }
}
