// 
// Decompiled by Procyon v0.6.0
// 

package com.google.protobuf;

import java.util.Collections;
import java.util.Collection;
import java.util.ArrayList;
import java.util.List;

@CheckReturnValue
final class ListFieldSchemaFull implements ListFieldSchema
{
    private static final Class<?> UNMODIFIABLE_LIST_CLASS;
    
    @Override
    public <L> List<L> mutableListAt(final Object message, final long offset) {
        return mutableListAt(message, offset, 10);
    }
    
    private static <L> List<L> mutableListAt(final Object message, final long offset, final int additionalCapacity) {
        List<L> list = getList(message, offset);
        if (list.isEmpty()) {
            if (list instanceof LazyStringList) {
                list = (List<L>)new LazyStringArrayList(additionalCapacity);
            }
            else if (list instanceof PrimitiveNonBoxingCollection && list instanceof Internal.ProtobufList) {
                list = ((Internal.ProtobufList)list).mutableCopyWithCapacity(additionalCapacity);
            }
            else {
                list = new ArrayList<L>(additionalCapacity);
            }
            UnsafeUtil.putObject(message, offset, list);
        }
        else if (ListFieldSchemaFull.UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) {
            final ArrayList<L> newList = new ArrayList<L>(list.size() + additionalCapacity);
            newList.addAll((Collection<? extends L>)list);
            list = newList;
            UnsafeUtil.putObject(message, offset, list);
        }
        else if (list instanceof UnmodifiableLazyStringList) {
            final LazyStringArrayList newList2 = new LazyStringArrayList(list.size() + additionalCapacity);
            newList2.addAll((Collection<? extends String>)list);
            list = (List<L>)newList2;
            UnsafeUtil.putObject(message, offset, list);
        }
        else if (list instanceof PrimitiveNonBoxingCollection && list instanceof Internal.ProtobufList && !((Internal.ProtobufList)list).isModifiable()) {
            list = ((Internal.ProtobufList)list).mutableCopyWithCapacity(list.size() + additionalCapacity);
            UnsafeUtil.putObject(message, offset, list);
        }
        return list;
    }
    
    @Override
    public void makeImmutableListAt(final Object message, final long offset) {
        final List<?> list = (List<?>)UnsafeUtil.getObject(message, offset);
        Object immutable = null;
        if (list instanceof LazyStringList) {
            immutable = ((LazyStringList)list).getUnmodifiableView();
        }
        else {
            if (ListFieldSchemaFull.UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) {
                return;
            }
            if (list instanceof PrimitiveNonBoxingCollection && list instanceof Internal.ProtobufList) {
                if (((Internal.ProtobufList)list).isModifiable()) {
                    ((Internal.ProtobufList)list).makeImmutable();
                }
                return;
            }
            immutable = Collections.unmodifiableList(list);
        }
        UnsafeUtil.putObject(message, offset, immutable);
    }
    
    @Override
    public <E> void mergeListsAt(final Object msg, final Object otherMsg, final long offset) {
        final List<E> other = getList(otherMsg, offset);
        final List<E> mine = mutableListAt(msg, offset, other.size());
        final int size = mine.size();
        final int otherSize = other.size();
        if (size > 0 && otherSize > 0) {
            mine.addAll((Collection<? extends E>)other);
        }
        final List<E> merged = (size > 0) ? mine : other;
        UnsafeUtil.putObject(msg, offset, merged);
    }
    
    static <E> List<E> getList(final Object message, final long offset) {
        return (List)UnsafeUtil.getObject(message, offset);
    }
    
    static {
        UNMODIFIABLE_LIST_CLASS = Collections.unmodifiableList(Collections.emptyList()).getClass();
    }
}
