/*
 * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.glassfish.jaxb.runtime.v2.runtime.reflect;

import com.sun.istack.SAXException2;
import org.glassfish.jaxb.runtime.api.AccessorException;
import org.glassfish.jaxb.core.v2.ClassFactory;
import org.glassfish.jaxb.core.v2.TODO;
import org.glassfish.jaxb.core.v2.model.core.Adapter;
import org.glassfish.jaxb.core.v2.model.core.ID;
import org.glassfish.jaxb.runtime.v2.runtime.XMLSerializer;
import org.glassfish.jaxb.core.v2.runtime.unmarshaller.LocatorEx;
import org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.Patcher;
import org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext;
import jakarta.xml.bind.JAXBException;
import org.xml.sax.SAXException;

import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.Callable;

/**
 * Used to list individual values of a multi-value property, and
 * to pack individual values into a multi-value property.
 *
 * @author Kohsuke Kawaguchi (kk@kohsuke.org)
 */
public abstract class Lister<BeanT,PropT,ItemT,PackT> {

    protected Lister() {}

    /**
     * Iterates values of a multi-value property.
     *
     * @param context
     *      This parameter is used to support ID/IDREF handling.
     */
    public abstract org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator<ItemT> iterator(PropT multiValueProp, XMLSerializer context);

    /**
     * Setting values to a multi-value property starts by creating
     * a transient object called "pack" from the current field.
     */
    public abstract PackT startPacking(BeanT bean, Accessor<BeanT, PropT> acc) throws AccessorException;

    /**
     * Once the {@link #startPacking} is called, you can
     * add values to the pack by using this method.
     */
    public abstract void addToPack( PackT pack, ItemT newValue ) throws AccessorException;

    /**
     * Finally, call this method to
     * wraps up the {@code pack}. This method may update the field of
     * the given bean.
     */
    public abstract void endPacking( PackT pack, BeanT bean, Accessor<BeanT,PropT> acc ) throws AccessorException;

    /**
     * Clears the values of the property.
     */
    public abstract void reset(BeanT o,Accessor<BeanT,PropT> acc) throws AccessorException;


    /**
     * Gets a reference to the appropriate {@link Lister} object
     * if the field is a multi-value field. Otherwise null.
     *
     * @param fieldType
     *      the type of the field that stores the collection
     * @param idness
     *      ID-ness of the property.
     * @param adapter
     *      adapter to be used for individual items. can be null.
     */
    public static <BeanT,PropT,ItemT,PackT>
        Lister<BeanT,PropT,ItemT,PackT> create(Type fieldType,ID idness, Adapter<Type,Class> adapter) {

        Class rawType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(fieldType);
        Class itemType;

        Lister l;
        if( rawType.isArray() ) {
            itemType = rawType.getComponentType();
            l = getArrayLister(itemType);
        } else
        if( Collection.class.isAssignableFrom(rawType) ) {
            Type bt = Utils.REFLECTION_NAVIGATOR.getBaseClass(fieldType,Collection.class);
            if(bt instanceof ParameterizedType)
                itemType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)bt).getActualTypeArguments()[0]);
            else
                itemType = Object.class;
            l = new CollectionLister(getImplClass(rawType));
        } else
            return null;

        if(idness==ID.IDREF)
            l = new IDREFS(l,itemType);

        if(adapter!=null)
            l = new AdaptedLister(l,adapter.adapterType);

        return l;
    }

    private static Class getImplClass(Class<?> fieldType) {
        return ClassFactory.inferImplClass(fieldType,COLLECTION_IMPL_CLASSES);
    }

    /**
     * Cache instances of {@link ArrayLister}s.
     */
    private static final Map<Class,WeakReference<Lister>> arrayListerCache =
        Collections.synchronizedMap(new WeakHashMap<Class,WeakReference<Lister>>());

    /**
     * Creates a lister for array type.
     */
    private static Lister getArrayLister( Class componentType ) {
        Lister l=null;
        if(componentType.isPrimitive())
            l = primitiveArrayListers.get(componentType);
        else {
            WeakReference<Lister> wr = arrayListerCache.get(componentType);
            if(wr!=null)
                l = wr.get();
            if(l==null) {
                l = new ArrayLister(componentType);
                arrayListerCache.put(componentType,new WeakReference<Lister>(l));
            }
        }
        assert l!=null;
        return l;
    }

    /**
     * {@link Lister} for an array.
     *
     * <p>
     * Array packing is slower, but we expect this to be used less frequently than
     * the {@link CollectionLister}.
     */
    private static final class ArrayLister<BeanT,ItemT> extends Lister<BeanT,ItemT[],ItemT,Pack<ItemT>> {

        private final Class<ItemT> itemType;

        public ArrayLister(Class<ItemT> itemType) {
            this.itemType = itemType;
        }

        public org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator<ItemT> iterator(final ItemT[] objects, XMLSerializer context) {
            return new org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator<ItemT>() {
                int idx=0;
                public boolean hasNext() {
                    return idx<objects.length;
                }

                public ItemT next() {
                    return objects[idx++];
                }
            };
        }

        public Pack startPacking(BeanT current, Accessor<BeanT, ItemT[]> acc) {
            return new Pack<ItemT>(itemType);
        }

        public void addToPack(Pack<ItemT> objects, ItemT o) {
            objects.add(o);
        }

        public void endPacking( Pack<ItemT> pack, BeanT bean, Accessor<BeanT,ItemT[]> acc ) throws AccessorException {
            acc.set(bean,pack.build());
        }

        public void reset(BeanT o,Accessor<BeanT,ItemT[]> acc) throws AccessorException {
            acc.set(o,(ItemT[])Array.newInstance(itemType,0));
        }

    }

    public static final class Pack<ItemT> extends ArrayList<ItemT> {
        private final Class<ItemT> itemType;

        public Pack(Class<ItemT> itemType) {
            this.itemType = itemType;
        }

        public ItemT[] build() {
            return super.toArray( (ItemT[])Array.newInstance(itemType,size()) );
        }
    }

    /**
     * Listers for the primitive type arrays, keyed by their primitive Class object.
     */
    /*package*/ static final Map<Class,Lister> primitiveArrayListers = new HashMap<Class,Lister>();

    static {
        // register primitive array listers
        PrimitiveArrayListerBoolean.register();
        PrimitiveArrayListerByte.register();
        PrimitiveArrayListerCharacter.register();
        PrimitiveArrayListerDouble.register();
        PrimitiveArrayListerFloat.register();
        PrimitiveArrayListerInteger.register();
        PrimitiveArrayListerLong.register();
        PrimitiveArrayListerShort.register();
    }

    /**
     * {@link Lister} for a collection
     */
    public static final class CollectionLister<BeanT,T extends Collection> extends Lister<BeanT,T,Object,T> {

        /**
         * Sometimes we need to create a new instance of a collection.
         * This is such an implementation class.
         */
        private final Class<? extends T> implClass;

        public CollectionLister(Class<? extends T> implClass) {
            this.implClass = implClass;
        }

        public org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator iterator(T collection, XMLSerializer context) {
            final Iterator itr = collection.iterator();
            return new org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator() {
                public boolean hasNext() {
                    return itr.hasNext();
                }
                public Object next() {
                    return itr.next();
                }
            };
        }

        public T startPacking(BeanT bean, Accessor<BeanT, T> acc) throws AccessorException {
            T collection = acc.get(bean);
            if(collection==null) {
                collection = ClassFactory.create(implClass);
                if(!acc.isAdapted())
                    acc.set(bean,collection);
            }
            collection.clear();
            return collection;
        }

        public void addToPack(T collection, Object o) {
            collection.add(o);
        }

        public void endPacking( T collection, BeanT bean, Accessor<BeanT,T> acc ) throws AccessorException {
            // this needs to be done in the endPacking, because
            // sometimes the accessor uses an adapter, and the adapter needs to see
            // the whole thing.

            // but always doing so causes a problem when this collection property
            // is getter-only

            // invoke set when possible (see Issue 488)
            try {
                if (acc.isAdapted()) {
                    acc.set(bean,collection);
                }
            } catch (AccessorException ae) {
                if(acc.isAdapted()) throw ae;
            }
        }

        public void reset(BeanT bean, Accessor<BeanT, T> acc) throws AccessorException {
            T collection = acc.get(bean);
            if(collection == null) {
                return;
            }
            collection.clear();
        }
    }

    /**
     * {@link Lister} for IDREFS.
     */
    private static final class IDREFS<BeanT,PropT> extends Lister<BeanT,PropT,String,IDREFS<BeanT,PropT>.Pack> {
        private final Lister<BeanT,PropT,Object,Object> core;
        /**
         * Expected type to which IDREF resolves to.
         */
        private final Class itemType;

        public IDREFS(Lister core, Class itemType) {
            this.core = core;
            this.itemType = itemType;
        }

        public org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator<String> iterator(PropT prop, XMLSerializer context) {
            final org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator i = core.iterator(prop,context);

            return new IDREFSIterator(i, context);
        }

        public Pack startPacking(BeanT bean, Accessor<BeanT, PropT> acc) {
            return new Pack(bean,acc);
        }

        public void addToPack(Pack pack, String item) {
            pack.add(item);
        }

        public void endPacking(Pack pack, BeanT bean, Accessor<BeanT, PropT> acc) {
        }

        public void reset(BeanT bean, Accessor<BeanT, PropT> acc) throws AccessorException {
            core.reset(bean,acc);
        }

        /**
         * PackT for this lister.
         */
        private class Pack implements Patcher {
            private final BeanT bean;
            private final List<String> idrefs = new ArrayList<String>();
            private final UnmarshallingContext context;
            private final Accessor<BeanT,PropT> acc;
            private final LocatorEx location;

            public Pack(BeanT bean, Accessor<BeanT,PropT> acc) {
                this.bean = bean;
                this.acc = acc;
                this.context = UnmarshallingContext.getInstance();
                this.location = new LocatorEx.Snapshot(context.getLocator());
                context.addPatcher(this);
            }

            public void add(String item) {
                idrefs.add(item);
            }

            /**
             * Resolves IDREFS and fill in the actual array.
             */
            public void run() throws SAXException {
                try {
                    Object pack = core.startPacking(bean,acc);

                    for( String id : idrefs ) {
                        Callable callable = context.getObjectFromId(id,itemType);
                        Object t;

                        try {
                            t = (callable!=null) ? callable.call() : null;
                        } catch (SAXException e) {
                            throw e;
                        } catch (Exception e) {
                            throw new SAXException2(e);
                        }

                        if(t==null) {
                            context.errorUnresolvedIDREF(bean,id,location);
                        } else {
                            TODO.prototype(); // TODO: check if the type of t is proper.
                            core.addToPack(pack,t);
                        }
                    }

                    core.endPacking(pack,bean,acc);
                } catch (AccessorException e) {
                    context.handleError(e);
                }
            }
        }
    }

    /**
     * {@link Iterator} for IDREFS lister.
     *
     * <p>
     * Only in ArrayElementProperty we need to get the actual
     * referenced object. This is a kind of ugly way to make that work.
     */
    public static final class IDREFSIterator implements org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator<String> {
        private final org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator i;
        private final XMLSerializer context;
        private Object last;

        private IDREFSIterator(org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator i, XMLSerializer context) {
            this.i = i;
            this.context = context;
        }

        public boolean hasNext() {
            return i.hasNext();
        }

        /**
         * Returns the last referenced object (not just its ID)
         */
        public Object last() {
            return last;
        }

        public String next() throws SAXException, JAXBException {
            last = i.next();
            String id = context.grammar.getBeanInfo(last,true).getId(last,context);
            if(id==null) {
                context.errorMissingId(last);
            }
            return id;
        }
    }

    /**
     * Gets the special {@link Lister} used to recover from an error.
     */
    @SuppressWarnings("unchecked")
    public static <A,B,C,D> Lister<A,B,C,D> getErrorInstance() {
        return ERROR;
    }

    public static final Lister ERROR = new Lister() {
        public org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator iterator(Object o, XMLSerializer context) {
            return EMPTY_ITERATOR;
        }

        public Object startPacking(Object o, Accessor accessor) {
            return null;
        }

        public void addToPack(Object o, Object o1) {
        }

        public void endPacking(Object o, Object o1, Accessor accessor) {
        }

        public void reset(Object o, Accessor accessor) {
        }
    };

    private static final org.glassfish.jaxb.runtime.v2.runtime.reflect.ListIterator EMPTY_ITERATOR = new ListIterator() {
        public boolean hasNext() {
            return false;
        }

        public Object next() {
            throw new IllegalStateException();
        }
    };

    private static final Class[] COLLECTION_IMPL_CLASSES = new Class[] {
        ArrayList.class,
        LinkedList.class,
        HashSet.class,
        TreeSet.class,
        Stack.class
    };
}
