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

package org.bson.codecs.pojo;

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

final class PojoSpecializationHelper
{
    static <V> TypeData<V> specializeTypeData(final TypeData<V> typeData, final List<TypeData<?>> typeParameters, final TypeParameterMap typeParameterMap) {
        if (!typeParameterMap.hasTypeParameters() || typeParameters.isEmpty()) {
            return typeData;
        }
        final Map<Integer, Either<Integer, TypeParameterMap>> propertyToClassParamIndexMap = typeParameterMap.getPropertyToClassParamIndexMap();
        final Either<Integer, TypeParameterMap> classTypeParamRepresentsWholeField = propertyToClassParamIndexMap.get(-1);
        if (classTypeParamRepresentsWholeField != null) {
            final Integer index = classTypeParamRepresentsWholeField.map(i -> i, e -> {
                throw new IllegalStateException("Invalid state, the whole class cannot be represented by a subtype.");
            });
            return (TypeData)typeParameters.get(index);
        }
        return getTypeData(typeData, typeParameters, propertyToClassParamIndexMap);
    }
    
    private static <V> TypeData<V> getTypeData(final TypeData<V> typeData, final List<TypeData<?>> specializedTypeParameters, final Map<Integer, Either<Integer, TypeParameterMap>> propertyToClassParamIndexMap) {
        final List<TypeData<?>> subTypeParameters = new ArrayList<TypeData<?>>(typeData.getTypeParameters());
        for (int i = 0; i < typeData.getTypeParameters().size(); ++i) {
            subTypeParameters.set(i, getTypeData(subTypeParameters.get(i), specializedTypeParameters, propertyToClassParamIndexMap, i));
        }
        return TypeData.builder(typeData.getType()).addTypeParameters(subTypeParameters).build();
    }
    
    private static TypeData<?> getTypeData(final TypeData<?> typeData, final List<TypeData<?>> specializedTypeParameters, final Map<Integer, Either<Integer, TypeParameterMap>> propertyToClassParamIndexMap, final int index) {
        if (!propertyToClassParamIndexMap.containsKey(index)) {
            return typeData;
        }
        return (TypeData)propertyToClassParamIndexMap.get(index).map(l -> {
            if (typeData.getTypeParameters().isEmpty()) {
                return specializedTypeParameters.get(l);
            }
            else {
                final TypeData.Builder<?> builder = TypeData.builder(typeData.getType());
                final List<TypeData<?>> typeParameters = new ArrayList<TypeData<?>>(typeData.getTypeParameters());
                typeParameters.set(index, specializedTypeParameters.get(l));
                builder.addTypeParameters(typeParameters);
                return builder.build();
            }
        }, r -> getTypeData((TypeData<Object>)typeData, specializedTypeParameters, r.getPropertyToClassParamIndexMap()));
    }
    
    private PojoSpecializationHelper() {
    }
}
