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

package com.google.protobuf;

import java.util.Iterator;

public final class GeneratorNames
{
    private GeneratorNames() {
    }
    
    public static String getFileJavaPackage(final DescriptorProtos.FileDescriptorProtoOrBuilder file) {
        return getProto2ApiDefaultJavaPackage(file.getOptions(), file.getPackage());
    }
    
    public static String getFileJavaPackage(final Descriptors.FileDescriptor file) {
        return getProto2ApiDefaultJavaPackage(file.getOptions(), file.getPackage());
    }
    
    static String getDefaultJavaPackage(final DescriptorProtos.FileOptions fileOptions, final String filePackage) {
        if (fileOptions.hasJavaPackage()) {
            return fileOptions.getJavaPackage();
        }
        return filePackage;
    }
    
    static String joinPackage(final String a, final String b) {
        if (a.isEmpty()) {
            return b;
        }
        if (b.isEmpty()) {
            return a;
        }
        return a + '.' + b;
    }
    
    static String getProto2ApiDefaultJavaPackage(final DescriptorProtos.FileOptions fileOptions, final String filePackage) {
        return getDefaultJavaPackage(fileOptions, filePackage);
    }
    
    public static String getFileClassName(final DescriptorProtos.FileDescriptorProtoOrBuilder file) {
        return getFileClassNameImpl(file, getResolvedFileFeatures(JavaFeaturesProto.java_, file));
    }
    
    public static String getFileClassName(final Descriptors.FileDescriptor file) {
        return getFileClassNameImpl(file.toProto(), file.getFeatures().getExtension(JavaFeaturesProto.java_));
    }
    
    private static String getFileClassNameImpl(final DescriptorProtos.FileDescriptorProtoOrBuilder file, final JavaFeaturesProto.JavaFeatures resolvedFeatures) {
        if (file.getOptions().hasJavaOuterClassname()) {
            return file.getOptions().getJavaOuterClassname();
        }
        final String className = getDefaultFileClassName(file, resolvedFeatures.getUseOldOuterClassnameDefault());
        if (resolvedFeatures.getUseOldOuterClassnameDefault() && hasConflictingClassName(file, className)) {
            return className + "OuterClass";
        }
        return className;
    }
    
    static <T extends Message> T getResolvedFileFeatures(final GeneratedMessage.GeneratedExtension<DescriptorProtos.FeatureSet, T> ext, final DescriptorProtos.FileDescriptorProtoOrBuilder file) {
        DescriptorProtos.Edition edition;
        if (file.getSyntax().equals("proto3")) {
            edition = DescriptorProtos.Edition.EDITION_PROTO3;
        }
        else if (!file.hasEdition()) {
            edition = DescriptorProtos.Edition.EDITION_PROTO2;
        }
        else {
            edition = file.getEdition();
        }
        DescriptorProtos.FeatureSet features = file.getOptions().getFeatures();
        if (features.getUnknownFields().hasField(ext.getNumber())) {
            final ExtensionRegistry registry = ExtensionRegistry.newInstance();
            registry.add(ext);
            try {
                features = ((AbstractMessage.Builder<DescriptorProtos.FeatureSet.Builder>)DescriptorProtos.FeatureSet.newBuilder()).mergeFrom(features.getUnknownFields().toByteString(), registry).build();
            }
            catch (final InvalidProtocolBufferException e) {
                throw new IllegalArgumentException("Failed to parse features", e);
            }
        }
        return (T)Descriptors.getEditionDefaults(edition).getExtension(ext).toBuilder().mergeFrom(features.getExtension(ext)).build();
    }
    
    static String getDefaultFileClassName(final DescriptorProtos.FileDescriptorProtoOrBuilder file, final boolean useOldOuterClassnameDefault) {
        String name = file.getName();
        name = name.substring(name.lastIndexOf(47) + 1);
        name = underscoresToCamelCase(stripProto(name));
        return useOldOuterClassnameDefault ? name : (name + "Proto");
    }
    
    private static String stripProto(final String filename) {
        if (filename.endsWith(".protodevel")) {
            return filename.substring(0, filename.length() - ".protodevel".length());
        }
        if (filename.endsWith(".proto")) {
            return filename.substring(0, filename.length() - ".proto".length());
        }
        return filename;
    }
    
    private static boolean hasConflictingClassName(final DescriptorProtos.FileDescriptorProtoOrBuilder file, final String name) {
        for (final DescriptorProtos.EnumDescriptorProto enumDesc : file.getEnumTypeList()) {
            if (name.equals(enumDesc.getName())) {
                return true;
            }
        }
        for (final DescriptorProtos.ServiceDescriptorProto serviceDesc : file.getServiceList()) {
            if (name.equals(serviceDesc.getName())) {
                return true;
            }
        }
        for (final DescriptorProtos.DescriptorProto messageDesc : file.getMessageTypeList()) {
            if (hasConflictingClassName(messageDesc, name)) {
                return true;
            }
        }
        return false;
    }
    
    private static boolean hasConflictingClassName(final DescriptorProtos.DescriptorProto messageDesc, final String name) {
        if (name.equals(messageDesc.getName())) {
            return true;
        }
        for (final DescriptorProtos.EnumDescriptorProto enumDesc : messageDesc.getEnumTypeList()) {
            if (name.equals(enumDesc.getName())) {
                return true;
            }
        }
        for (final DescriptorProtos.DescriptorProto nestedMessageDesc : messageDesc.getNestedTypeList()) {
            if (hasConflictingClassName(nestedMessageDesc, name)) {
                return true;
            }
        }
        return false;
    }
    
    static String underscoresToCamelCase(final String input, boolean capitalizeNextLetter) {
        final StringBuilder result = new StringBuilder();
        for (int i = 0; i < input.length(); ++i) {
            final char ch = input.charAt(i);
            if ('a' <= ch && ch <= 'z') {
                if (capitalizeNextLetter) {
                    result.append((char)(ch - 32));
                }
                else {
                    result.append(ch);
                }
                capitalizeNextLetter = false;
            }
            else if ('A' <= ch && ch <= 'Z') {
                if (i == 0 && !capitalizeNextLetter) {
                    result.append((char)(ch + ' '));
                }
                else {
                    result.append(ch);
                }
                capitalizeNextLetter = false;
            }
            else if ('0' <= ch && ch <= '9') {
                result.append(ch);
                capitalizeNextLetter = true;
            }
            else {
                capitalizeNextLetter = true;
            }
        }
        return result.toString();
    }
    
    static String underscoresToCamelCase(final String input) {
        return underscoresToCamelCase(input, true);
    }
    
    public static String getBytecodeClassName(final Descriptors.Descriptor message) {
        return getClassFullName(getClassNameWithoutPackage(message), message.getFile(), !getNestInFileClass(message));
    }
    
    public static String getBytecodeClassName(final Descriptors.EnumDescriptor enm) {
        return getClassFullName(getClassNameWithoutPackage(enm), enm.getFile(), !getNestInFileClass(enm));
    }
    
    static String getBytecodeClassName(final Descriptors.ServiceDescriptor service) {
        final String suffix = "";
        final boolean isOwnFile = !getNestInFileClass(service);
        return getClassFullName(getClassNameWithoutPackage(service), service.getFile(), isOwnFile) + suffix;
    }
    
    static String getQualifiedFromBytecodeClassName(final String bytecodeClassName) {
        return bytecodeClassName.replace('$', '.');
    }
    
    public static String getQualifiedClassName(final Descriptors.Descriptor message) {
        return getQualifiedFromBytecodeClassName(getBytecodeClassName(message));
    }
    
    public static String getQualifiedClassName(final Descriptors.EnumDescriptor enm) {
        return getQualifiedFromBytecodeClassName(getBytecodeClassName(enm));
    }
    
    public static String getQualifiedClassName(final Descriptors.ServiceDescriptor service) {
        return getQualifiedFromBytecodeClassName(getBytecodeClassName(service));
    }
    
    private static String getClassFullName(final String nameWithoutPackage, final Descriptors.FileDescriptor file, final boolean isOwnFile) {
        final StringBuilder result = new StringBuilder();
        if (isOwnFile) {
            result.append(getFileJavaPackage(file.toProto()));
            if (result.length() > 0) {
                result.append(".");
            }
        }
        else {
            result.append(joinPackage(getFileJavaPackage(file.toProto()), getFileClassName(file)));
            if (result.length() > 0) {
                result.append("$");
            }
        }
        result.append(nameWithoutPackage.replace('.', '$'));
        return result.toString();
    }
    
    private static boolean getNestInFileClass(final Descriptors.FileDescriptor file, final JavaFeaturesProto.JavaFeatures resolvedFeatures) {
        switch (resolvedFeatures.getNestInFileClass()) {
            case YES: {
                return true;
            }
            case NO: {
                return false;
            }
            case LEGACY: {
                return !file.getOptions().getJavaMultipleFiles();
            }
            default: {
                throw new IllegalArgumentException("Java features are not resolved");
            }
        }
    }
    
    public static boolean getNestInFileClass(final Descriptors.Descriptor descriptor) {
        return getNestInFileClass(descriptor.getFile(), descriptor.getFeatures().getExtension(JavaFeaturesProto.java_));
    }
    
    public static boolean getNestInFileClass(final Descriptors.EnumDescriptor descriptor) {
        return getNestInFileClass(descriptor.getFile(), descriptor.getFeatures().getExtension(JavaFeaturesProto.java_));
    }
    
    private static boolean getNestInFileClass(final Descriptors.ServiceDescriptor descriptor) {
        return getNestInFileClass(descriptor.getFile(), descriptor.getFeatures().getExtension(JavaFeaturesProto.java_));
    }
    
    static String stripPackageName(final String fullName, final Descriptors.FileDescriptor file) {
        if (file.getPackage().isEmpty()) {
            return fullName;
        }
        return fullName.substring(file.getPackage().length() + 1);
    }
    
    static String getClassNameWithoutPackage(final Descriptors.Descriptor message) {
        return stripPackageName(message.getFullName(), message.getFile());
    }
    
    static String getClassNameWithoutPackage(final Descriptors.EnumDescriptor enm) {
        final Descriptors.Descriptor containingType = enm.getContainingType();
        if (containingType == null) {
            return enm.getName();
        }
        return joinPackage(getClassNameWithoutPackage(containingType), enm.getName());
    }
    
    static String getClassNameWithoutPackage(final Descriptors.ServiceDescriptor service) {
        return stripPackageName(service.getFullName(), service.getFile());
    }
}
